ClassNotFoundException when deserializing a binary class file's contents
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.
Gabriele Cirulli
Updated on June 26, 2022Comments
-
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 about 13 yearsPlease show the details of the exception.
-
appbootup about 13 yearsCan you provide a few more details, ideally the stacktrace?
-
McDowell about 13 yearsare you deserializing the exact same class that was written? Is the
Automobile
type in your deserialization code in thees4
package?
-
-
Gabriele Cirulli about 13 yearsI added that to the class, I still get the issue.
-
Gabriele Cirulli about 13 yearsWhat 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 about 13 yearsCould the problem be caused by a custom exception I made which is fired by Automobile?
-
Gabriele Cirulli about 13 yearsI 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 about 13 yearsThanks. I decided I'll merge the two projects instead of messing with them further
-
Angel O'Sphere about 13 yearsThe 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 over 8 yearsOmitting it doesn't cause this problem.
-
user207421 over 8 yearsYou 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 over 6 yearsWhy do they not use the currentThread classloader?! Thanks for your inspiration.
-
Stephen C over 2 yearsClasses 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.)