1

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?

Gavriel
  • 18,880
  • 12
  • 68
  • 105
peter
  • 78
  • 9
  • Check the Directory class – Gabriele Mariotti Feb 23 '16 at 09:02
  • If you're trying to read a serialized collection which refers to the old `com.company.Clerk` class and you moved that class to a new package, you won't be able to read it because java will look for the old path. – StepTNT Feb 23 '16 at 09:07
  • You might try to write your own classloader: https://dzone.com/articles/java-classloader-handling – Gavriel Feb 23 '16 at 09:09

2 Answers2

2

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.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • this is all true, but IMHO it doesn't help OP, as he seems to know all this, he stated he REFACTORED the code and changed the package and wants to deserialize something that was serialized before the refactoring – Gavriel Feb 23 '16 at 09:06
  • @Gavriel Good point, then the OP really already knows the solution but what the OP doesn't know is there really is no alternative for built in Java serialization (Unless he creates a custom class loader) Some other serialization libraries do support aliases. – Peter Lawrey Feb 23 '16 at 09:24
0

The objects stored in the file have the class com.company.Clerk. That class stopped existing when you changed its name, so obviously it's impossible to read the objects anymore. Your options are: change the name of the class back to what it was, or create a program to convert files from one format to the other, or accept that you'll lose the data in the file and get on with your life, or add code that resolves the old class name as the new class (override resolveClass method).

Joni
  • 108,737
  • 14
  • 143
  • 193