反序列化二进制类文件的内容时ClassNotFoundException

我对Java知之甚少。 我正在尝试读取包含int的文件以及名为“Automobile”的类的各种实例。 但是,当我反序列化它时,程序抛出一个ClassNotFoundException,我似乎无法理解为什么。

这是代码:

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"); } 

提前致谢。

编辑:这是堆栈跟踪

 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) 

反序列化序列化对象树时,所有对象的类必须位于类路径上。 在此上下文中, ClassNotFoundException很可能意味着所需的类之一不在类路径上。 您必须解决此问题才能使反序列化工作。

在这种情况下, es4.Automobile缺失。


这个问题可能是由我所做的自定义exception导致的吗?

我能想到的唯一其他可能性是:

  • es4.Automobile直接或间接依赖于其他一些缺失的类
  • es4.Automobile或依赖类的静态初始化抛出了一个未在类内部捕获的exception。

但是这两者都应该(我认为)导致了不同的堆栈跟踪。


我刚注意到包名是es4p2,而不是es4。 为什么说es4? 可能是因为保存文件的程序使用另一个包名?

我不知道他们为什么会有所不同。 您需要与编写代码/生成序列化对象的人交谈。 但是,这很可能是导致问题的原因。 具有不同包名称的类是不同的类。 期。


捕获意外exception时,应始终输出(或更好地,记录)堆栈跟踪。 这将告诉你(和我们)更多关于出错的地方,在这种情况下,缺少类的名称。

如果您的类Automobile不在运行时类路径中,则通常会发生这种情况。

这是一个古老的问题,但这可能有助于其他人。 我面临同样的问题,问题是我没有使用当前的线程类加载器。 您将在下面找到我在grails项目中使用的序列化程序类,应该非常直接在java中使用它希望这有助于

 public final class Serializer { /** * 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 } } } 

你的Automobile类有这样的领域吗?

 private static final long serialVersionUID = 140605814607823206L; // some unique number 

如果没有,请定义一个。 如果有问题,请告诉我们。

我以比其他答案更简单的方式修复它 – 在多个项目中使用该类时出现了我的问题。

如果您有多个项目,请确保您要反序列化的特定类在完全相同的路径中! 这意味着,该项目中的相同包名等。 否则它将找不到它并导致抛出ClassNotFoundException

所以,如果它在

/myPackage/otherPackage/Test.java

然后确保该路径在您的其他项目中完全相同。

我有一个类似的问题与ObjectInputStream读取序列化对象。 我在运行时使用URLClassloader添加的那些对象的类。 问题是ObjectInputStream没有使用我设置的Thread ClassLoader

 Thread.currentThread().setContextClassLoader(cl); 

而是AppClassLoader,你不能用java 9自定义。所以我把我自己的ObjectInputStream作为原始的一个子类型,并覆盖了resolveClass方法:

 @Override protected Class resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException { String name = desc.getName(); try { return Class.forName(name, false, Thread.currentThread() .getContextClassLoader()); } catch (ClassNotFoundException ex) { Class cl = primClasses.get(name); if (cl != null) { return cl; } else { throw ex; } } } 

你可以从ClassNotFoundexception的消息中访问类名 – 在代码中依赖于它是可怕的 – 但它应该给你一些想法。 我希望有一些更好的方法来获取有关序列化对象的信息,而无需使用该类。