ClassNotFoundException when deserializing a binary class file's contents

11,879

Solution 1

When you deserialize a serialized object tree, the classes of all the objects have to be on the classpath. In this context, a ClassNotFoundException most likely means that one of the classes required is not on the classpath. You have to address this for deserialization to work.

In this case, the es4.Automobile is missing.


Could the problem be caused by a custom exception I made which is fired by Automobile?

The only other possibilities I can think of are:

  • es4.Automobile has a direct or indirect dependency on some other class that is missing
  • the static initialization of es4.Automobile or a dependent class has thrown an exception that has not been caught internally to the class.

But both of those should (I think) have resulted in a different stack trace.


I just noticed the package name is es4p2, not es4. Why does it say es4? Could it be because the program which saves the file uses another package name?

I've no idea why they are different. You'd need to talk to whoever wrote the code / produced the serialized objects. However, this is most likely the cause of your problem. A class with a different package name is a different class. Period.


You should always output (or better, log) the stacktrace when an unexpected exception is caught. That will tell you (and us) more about what has gone wrong, and in this case the name of the class that is missing.

Solution 2

This is and old question but this may help someone else. I faced the same issue and the problem was that I was not using the current thread class loader. You will find below the serializer class that I used in a grails project, should be quite straightforward use this in java Hope this helps

public final class Serializer<T> {

/**
 * Converts an Object to a byte array.
 *
 * @param object, the Object to serialize.
 * @return, the byte array that stores the serialized object.
 */

public static byte[] serialize(T object) {

    ByteArrayOutputStream bos = new ByteArrayOutputStream()
    ObjectOutput out = null
    try {
        out = new ObjectOutputStream(bos)
        out.writeObject(object)

        byte[] byteArray = bos.toByteArray()
        return byteArray

    } catch (IOException e) {
        e.printStackTrace()
        return null

    } finally {
        try {
            if (out != null)
                out.close()
        } catch (IOException ex) {
            ex.printStackTrace()
            return null
        }
        try {
            bos.close()
        } catch (IOException ex) {
            ex.printStackTrace()
            return null
        }
    }

}

/**
 * Converts a byte array to an Object.
 *
 * @param byteArray, a byte array that represents a serialized Object.
 * @return, an instance of the Object class.
 */
public static Object deserialize(byte[] byteArray) {
    ByteArrayInputStream bis = new ByteArrayInputStream(byteArray)
    ObjectInput input = null
    try {
        input = new ObjectInputStream(bis){
            @Override protected Class<?> resolveClass(final ObjectStreamClass desc) throws IOException, ClassNotFoundException {
                ClassLoader cl = Thread.currentThread().getContextClassLoader();
                if (cl == null)  return super.resolveClass(desc);
                return Class.forName(desc.getName(), false, cl);
            }
        };
        Object o = input.readObject()
        return o

    } catch (ClassNotFoundException | IOException e) {
        e.printStackTrace()
        return null
    } finally {
        try {
            bis.close()
        } catch (IOException ex) {
        }
        try {
            if (input != null)
                input.close()
        } catch (IOException ex) {
            ex.printStackTrace()
            return null
        }
    }
}

Solution 3

This generally happens if your class Automobile is not in the runtime classpath.

Share:
11,879
Gabriele Cirulli
Author by

Gabriele Cirulli

Updated on June 26, 2022

Comments

  • Gabriele Cirulli
    Gabriele Cirulli about 2 years

    I don't know much about Java. I'm trying to read a file containing an int and various instances of a class called "Automobile". When I deserialize it, though, the program throws a ClassNotFoundException and I can't seem to understand why.

    Here's the code:

            try {
            FileInputStream fin = new FileInputStream(inputFile);
            ObjectInputStream input = new ObjectInputStream(fin);
    
            conto = input.readInt();
    
            Automobile[] macchine = new Automobile[conto];
    
            for(int i = 0; i < conto; i++) {
                macchine[i] = (Automobile)input.readObject();
            }
    
            String targa;
            System.out.print("\nInserire le cifre di una targa per rintracciare l'automobile: ");
            targa = sc1.nextLine();
    
            for(int i = 0; i < conto; i++) {
                if(macchine[i].getTarga().equals(targa))
                    System.out.println(macchine[i]);
            }
    
        } catch(IOException e) {
            System.out.println("Errore nella lettura del file "+inputFile);
        } catch(java.lang.ClassNotFoundException e) {
            System.out.println("Class not found");
        }
    

    Thanks in advance.

    EDIT: here's the stacktrace

    java.lang.ClassNotFoundException: es4.Automobile
        at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:248)
        at java.lang.Class.forName0(Native Method)
        at java.lang.Class.forName(Class.java:247)
        at java.io.ObjectInputStream.resolveClass(ObjectInputStream.java:604)
        at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1575)
        at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1496)
        at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1732)
        at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1329)
        at java.io.ObjectInputStream.readObject(ObjectInputStream.java:351)
        at es4p2.Main.main(Main.java:35)
    
    • Jon Skeet
      Jon Skeet about 13 years
      Please show the details of the exception.
    • appbootup
      appbootup about 13 years
      Can you provide a few more details, ideally the stacktrace?
    • McDowell
      McDowell about 13 years
      are you deserializing the exact same class that was written? Is the Automobile type in your deserialization code in the es4 package?
  • Gabriele Cirulli
    Gabriele Cirulli about 13 years
    I added that to the class, I still get the issue.
  • Gabriele Cirulli
    Gabriele Cirulli about 13 years
    What do you mean by the class "being in the classpath"? The file Automobile.java is in the same package as Main.java, which fires off the exception.
  • Gabriele Cirulli
    Gabriele Cirulli about 13 years
    Could the problem be caused by a custom exception I made which is fired by Automobile?
  • Gabriele Cirulli
    Gabriele Cirulli about 13 years
    I just noticed the package name is es4p2, not es4. Why does it say es4? Could it be because the program which saves the file uses another package name?
  • Gabriele Cirulli
    Gabriele Cirulli about 13 years
    Thanks. I decided I'll merge the two projects instead of messing with them further
  • Angel O'Sphere
    Angel O'Sphere about 13 years
    The saved Automobile was an es4.Automobile, and now you want to deserialze it "into" an es4p2.Automobile (without having the other one in your classpath) obviously that can't work. How should the deserialization know that you now want to have "an nother kind of Automobile"?
  • user207421
    user207421 over 8 years
    Omitting it doesn't cause this problem.
  • user207421
    user207421 over 8 years
    You don't have to 'depend on this in the code'. You just have to deploy your application correctly. No idea what exactly you are wishing for in your last sentence.
  • Kuronashi
    Kuronashi over 6 years
    Why do they not use the currentThread classloader?! Thanks for your inspiration.
  • Stephen C
    Stephen C over 2 years
    Classes with the same simple name but different package names are different classes. That's a fundamental of the Java type system. (And the "path" is derived from the package name.)