在Weblogic 12c中反序列化时ClassNotFoundException

时间:2016-12-13 15:03:12

标签: java serialization weblogic12c

我有一个webapp,可以在客户端保存状态。州被累积为Object []

Object state[] = new Object[10];

state[0] = _parent_s_state_array
state[1] = _some_int;
state[2] = _some_POJO;
..
..

然后是

  • 序列化
  • Base64编码
  • 作为回复中的隐藏输入包含在内

在下一个请求中,这个序列化状态被提交回来,我们反转在服务器端重建状态的步骤。这个策略适用于几百页。

但对于使用具有少量String属性的特定POJO的某个页面,我在反序列化时得到ClassNotFoundException。需要注意的是,同一个类的对象在不久之前在同一个JVM会话中创建并序列化,因此我们可以排除Class不存在于类路径中。

更多观察

  • 此错误仅出现在 Weblogic 12c 的生产和测试平台中,并且从未在开发中看到它在jetty 8或9中运行。所以我猜这与Weblogic的某种方式有关类加载。
  • 此问题始终在该特定页面中复制。
  • 在同一平台上还有其他页面使用相同的违规类而没有任何问题。
  • 从爆炸的war目录部署webapp,WEB-INF/classes/com/xxx/yyy/
  • 中存在相关课程

有人可以为调试此问题提供一些指示/策略。

提前致谢。

异常

ERROR [[ACTIVE] ExecuteThread: '5' for queue: 'weblogic.kernel.Default (self-tuning)'] ClassNotFoundException occured restoring StateManager state from serialized form
java.lang.ClassNotFoundException: com.xxx.yyy.TimeParameters
        at java.net.URLClassLoader$1.run(URLClassLoader.java:366) ~[na:1.7.0_65]
        at java.net.URLClassLoader$1.run(URLClassLoader.java:355) ~[na:1.7.0_65]
        at java.security.AccessController.doPrivileged(Native Method) ~[na:1.7.0_65]
        at java.net.URLClassLoader.findClass(URLClassLoader.java:354) ~[na:1.7.0_65]
        at java.lang.ClassLoader.loadClass(ClassLoader.java:425) ~[na:1.7.0_65]
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308) ~[na:1.7.0_65]
        at java.lang.ClassLoader.loadClass(ClassLoader.java:358) ~[na:1.7.0_65]
        at java.lang.Class.forName0(Native Method) [na:1.7.0_65]
        at java.lang.Class.forName(Class.java:270) [na:1.7.0_65]
        at java.io.ObjectInputStream.resolveClass(ObjectInputStream.java:625) ~[na:1.7.0_65]
        at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1612) ~[na:1.7.0_65]
        at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1517) ~[na:1.7.0_65]
        at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1771) ~[na:1.7.0_65]
        at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1350) ~[na:1.7.0_65]
        at java.io.ObjectInputStream.readObject(ObjectInputStream.java:370) ~[na:1.7.0_65]
        at org.apache.commons.collections.map.AbstractHashedMap.doReadObject(AbstractHashedMap.java:1212) ~[weblogic.server.merged.jar:12.1.3.0.0]
        at org.apache.commons.collections.map.CaseInsensitiveMap.readObject(CaseInsensitiveMap.java:149) ~[weblogic.server.merged.jar:12.1.3.0.0]

package com.xxx.yyy;
public class TimeParameters implements Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = 5384703411813811209L;
    private String yr;
    private String qtr;
    private String mth;
    private String analysisType;

// Getters and Setters
...
...
}

2 个答案:

答案 0 :(得分:1)

TLDR;

Apache Commons集合中的一个类在序列化过程中涉及某个地方。由于apache-commons-collections是从Weblogic jar加载的,因此它导致在Application类加载器中搜索所需的类,无法找到它。修复是在org.apache.commons.collections.*

中将prefer-application-packages添加到weblogic.xml

详情

我做了一个远程调试器会话来跟踪对Class.forName0(String className, boolean, ClassLoader loader)的调用。

发现当加载所需的类 时,传递的类加载器具有更深的层次结构

this contains all classes in WEB-INF/classes --> weblogic.utils.classloaders.ChangeAwareClassLoader@6437e3af finder: weblogic.utils.classloaders.CodeGenClassFinder@2cd01c0c annotation: mi.8200@MedicalIntelligence 
weblogic.utils.classloaders.FilteringClassLoader@6413df9c finder: weblogic.utils.classloaders.CodeGenClassFinder@54bdae18 annotation: 
weblogic.utils.classloaders.GenericClassLoader@5919d25d finder: weblogic.utils.classloaders.CodeGenClassFinder@1265cb83 annotation: 
java.net.URLClassLoader@5a88cbff
Application classloader, contains classes from weblogic bundled jars -->  sun.misc.Launcher$AppClassLoader@2a9a42ef 
sun.misc.Launcher$ExtClassLoader@75a06ec2

当它抛出ClassNotFoundException它被缩短时 - 只有最后两个条目存在

sun.misc.Launcher$AppClassLoader@2a9a42ef <--   Hierarchy starts at Application classloader
sun.misc.Launcher$ExtClassLoader@75a06ec2

然后,我注意到堆栈跟踪包含以~[weblogic.server.merged.jar:12.1.3.0.0]结尾的这些行(编辑后的问题以添加更多堆栈跟踪)

    at org.apache.commons.collections.map.AbstractHashedMap.doReadObject(AbstractHashedMap.java:1212) ~[weblogic.server.merged.jar:12.1.3.0.0]
    at org.apache.commons.collections.map.CaseInsensitiveMap.readObject(CaseInsensitiveMap.java:149) ~[weblogic.server.merged.jar:12.1.3.0.0]

所以Apache commons集合是从weblogic捆绑的jar中加载的,即sun.misc.Launcher$AppClassLoader@2a9a42ef,这可能会触发错误的类加载器进一步向下传递。因此,在org.apache.commons.collections.*

中将prefer-application-packages添加到weblogic.xml
    <prefer-application-packages> 
        ...
        <package-name>org.apache.commons.collections.*</package-name>
    </prefer-application-packages> 

有用资源

答案 1 :(得分:0)

Java序列化不是完成任务的最佳方式。您最好将其序列化为(比如说)JSON,然后根据需要进行压缩。好的选择是google GSON。或者带有JSON驱动程序的XStream。或杰克逊......