Search code examples
javaclassnotfoundexception

ClassNotFoundException when deserializing after refactored package


I am running into a problem (broken classpath?) when I try to execute my program. The .class files are located in: C:\...\...\...\StoreDirectorySystem4.0\bin\build\classes\system, so I point the classpath to the system folder. I have also tried pointing to the jar file, but to no avail, following this:

When specifying a path to a .zip or .jar file, you must end the path with the filename. When specifying a path to .class files, that path should end with the folder containing the .class files. (source)

However, when I build the project (with ant), it throws a ClassNotFoundException. This is the stack trace:

    [java] java.lang.ClassNotFoundException: com.company.Clerk
    [java]     at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
    [java]     at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    [java]     at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
    [java]     at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    [java]     at java.lang.Class.forName0(Native Method)
    [java]     at java.lang.Class.forName(Class.java:348)
    [java]     at java.io.ObjectInputStream.resolveClass(ObjectInputStream.java :626)
    [java]     at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream. java:1613)
    [java]     at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1518)
    [java]     at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1774)
    [java]     at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351)
    [java]     at java.io.ObjectInputStream.readObject(ObjectInputStream.java:371)
    [java]     at java.util.ArrayList.readObject(ArrayList.java:791)
    [java]     at sun.reflect.NativeMethodAccessorImpl.invoke0(NativeMethod)
    [java]     at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    [java]     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    [java]     at java.lang.reflect.Method.invoke(Method.java:497)
    [java]     at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:1017)
    [java]     at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1900)
    [java]     at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1801)
    [java]     at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351)
    [java]     at java.io.ObjectInputStream.readObject(ObjectInputStream.java:371)
    [java]     at system.Directory.readFile(Unknown Source)
    [java]     at system.Directory.<init>(Unknown Source)
    [java]     at system.DirectoryServer.main(Unknown Source)

Problem is, the Clerk class no longer exists in com.company (I refactored the name of the package in IntelliJ IDEA). It exists in the system package mentioned before. The Clerk class has declared within it, package system;. The exception arises when I try to read in a serialized collection in the Directory class, specifically here:

public ArrayList<Employee> readFile() {
    try (ObjectInputStream inputStream =
                 new ObjectInputStream(new FileInputStream(this.file))) {
        employeeList = (ArrayList<Employee>) inputStream.readObject();
    } catch (ClassNotFoundException | IOException e) {
            e.printStackTrace();
    }
    return employeeList;
}

The jar file contains:

META-INF/
META-INF/MANIFEST.MF
system/
system/Clerk.class
system/Directory.class
system/DirectoryServer.class
system/Employee.class
system/FullTime.class
system/Manager.class
system/PartTime.class

So my question is, what is the problem, and how might it be resolved?


Solution

  • ClassNotFoundException: com.company.Clerk

    This means it could not find the class com.company.Clerk so you would need to have in your JAR com/company/Clerk.class or have the directory above com/company/Clerk.class in your class path.

    In short, the package has to match the directory the class is in.

    he stated he REFACTORED the code and changed the package and wants to deserialize something that was serialized before the refactoring

    This won't change the serialization format and the standard serialization doesn't support aliases or renaming. What you need to deserialize the original class and convert it to your new class at runtime.