org.apache.commons.lang.SerializationException:java.lang.ClassNotFoundException

时间:2015-10-29 06:11:31

标签: java spring osgi deserialization classloader

我正在使用org.apache.commons.lang.SerializationUtils,但是我收到了一个错误。如果您需要更多信息,我是Java新手,请告诉我 代码:

Profile profile2 = new Profile();
profile2.setFileName(path);
profile2.setStatus("UPLOADED");
byte[] payload2 = SerializationUtils.serialize(profile2);
profile = (Profile) SerializationUtils.deserialize(payload2);

运行时错误输出:

org.apache.commons.lang.SerializationException: java.lang.ClassNotFoundException: com.xxx.xxx.Profile
        at org.apache.commons.lang.SerializationUtils.deserialize(SerializationUtils.java:166)
        at org.apache.commons.lang.SerializationUtils.deserialize(SerializationUtils.java:193)

人们说Profile不在classpath中。如果确实如此,则会在“new Profile()”上发生错误。我是对的吗?

我刚刚找到了解决方法:

profile = (EveSuccessCriteriaProfile) SerializationUtils.deserialize(payload2);

替换为

InputStream fis = null;
fis = new ByteArrayInputStream(payload2);
ObjectInputStream o = new ObjectInputStream(fis);
profile = (Profile) o.readObject();

一切正常

1 个答案:

答案 0 :(得分:5)

问题是在OSGi中不仅有一次加载所有类的类加载器。每个包有一个类加载器。因此,如果您执行Profile.class.getClassLoader(),您将获得包含Profile的包的类加载器。如果您执行SerializationUtils.class.getClassLoder(),那么您将获得commons.lang包的类加载器。由于commons.lang没有一个Import-Package,因为包中的Profile不会看到它。 因此,如果SerializationUtils.deserialize使用自己的类加载器来加载Profile类,它将无法找到它。

我很确定它会尝试使用ThreadContext类加载器来加载用户类。所以它可能有所帮助     在调用SerializationUtils.deserialize之前Thread.currentThread().setContextClassLoader(Profile.class.getClassLoader());

这只是一种解决方法。应该增强反序列化调用以接受ClassLoader作为第二个参数。因此,不要进入habbit,将ContextClassLoader视为最佳实践。

不幸的是,SerializationUtils在OSGi中不起作用。您必须等待解决此问题:https://issues.apache.org/jira/browse/LANG-1049

您应该尝试使用https://commons.apache.org/proper/commons-io/apidocs/org/apache/commons/io/input/ClassLoaderObjectInputStream.html,以便在没有伙伴类加载或类似情况的情况下干净地进行反序列化。