【发布时间】:2014-07-21 20:41:01
【问题描述】:
我在反序列化对象时遇到问题。当前项目具有插件式架构,因此我有包含在运行时加载的类文件的 jar。我无法反序列化包含在其中一个 jar 中找到的类的对象,因此我编写了一个快速测试方法,该方法被称为中流,它刚刚加载了插件,实例化了正确的(对象实现了特定的接口所以我可以通过 .isAssignableFrom(..) 识别它,序列化它(这很好),然后立即尝试反序列化它。
我仍然收到“ClassNotFoundException”。
堆栈跟踪:
Jul 21, 2014 4:02:11 PM com.newspinrobotics.auth.MainFrame loadPlugins
SEVERE: null
java.lang.ClassNotFoundException: com.newspinrobotics.auth.plugin.tcpserver.TCPServer
at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:270)
at java.io.ObjectInputStream.resolveClass(ObjectInputStream.java:625)
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1612)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1517)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1771)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1350)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:370)
at com.newspinrobotics.auth.MainFrame.loadPlugins(MainFrame.java:79)
at com.newspinrobotics.auth.MainFrame.<init>(MainFrame.java:43)
at com.newspinrobotics.auth.MainFrame$6.run(MainFrame.java:539)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:251)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:733)
at java.awt.EventQueue.access$200(EventQueue.java:103)
at java.awt.EventQueue$3.run(EventQueue.java:694)
at java.awt.EventQueue$3.run(EventQueue.java:692)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:703)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:242)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:161)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:150)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:146)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:138)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:91)
现在,在你问之前。 TCPServer 类中没有不可序列化的字段。它有字符串和原语。有一个字段不属于这些类别,但它被标记为瞬态。甚至还有一个无参数的构造函数(虽然 不需要,对吗?)。是的,它实现了 Serializable (序列化很好)。
我很困惑类加载器怎么可能没有它,因为它在反序列化之前仅实例化对象几行。
我确实使用定制的 ClassLoader(扩展 URLClassLoader)在运行时加载 jar 文件。
我确实提供了一个 public static final long serialVersionUID = XXXXXXXL;字段。
编辑:
我所指的类加载器扩展了 URLClassLoader。它位于另一个人编写的实用程序类中,经过进一步检查,实际上甚至不是真正的修改(出于某种原因,他想扩展它而不是真正对其做任何实质性的事情)。该实用程序所做的只是挑选 jar 文件,并使用 URLClassLoader 通过 addURL(..) 将 jar 文件添加到 URLClassLoader 中,并通过 loadClass(..) 加载类。因此,该实用程序似乎没有任何恶意。但是,我不是 ClassLoader 忍者,因此如果需要,我当然可以提供更多信息。它实际上只是一些用于加载 Jar 文件和挑选类文件并加载它们的实用函数。
帮助我 StackOverflow,你是我唯一的希望(也许)。
【问题讨论】:
-
所以你已经实现了一个自定义 ClassLoader,你遇到了类加载问题,并且你没有发布任何类加载代码(自定义 ClassLoader 和使用它,包括首先构建 TCPServer 对象的代码)...
-
好吧。考虑到 ClassLoader 似乎可以用于实例化对象(以使它们完全可用的方式),问题似乎不在类加载器中。
-
您的自定义类加载器似乎不在您的堆栈跟踪中,这使得它在您反序列化时看起来好像没有被使用。因此,尽管它可能很好,但尝试使用它的代码(通过 ObjectInputStream)似乎不是。能发下相关代码吗?
-
你认为什么是相关的?整个类加载器实用程序?或者“修改后的类加载器”的定义最终根本没有被修改。它已扩展,但仅覆盖 addURL 并在其中简单地调用 super。所以根本没有真正扩展。
-
我不太关心 ClassLoader 本身(因为正如您所说,它可以在其他地方工作),而更多地关注您调用它的代码。因此,如果我们关于在我的答案的 cmets 中扩展
ObjectInputStream的讨论没有取得成果,我建议您发布您从类加载器成功实例化TCPServer的代码,以及您在其中的代码'从ObjectInputStream反序列化它失败(包括你实例化和配置ObjectInputStream的代码)。但希望扩展ObjectInputStream将是您所需要的。
标签: java serialization deserialization classloader classnotfoundexception