这两天开发时遇到个奇葩的问题,使用xStream实现xml和java bean互转。在eclipse中运行时xml转java bean一切正常,导入到产品里面去就运行就抛出CannotResolveClassException异常,于是开始查找原因。
具体异常信息如下:
Caused by: com.thoughtworks.xstream.mapper.CannotResolveClassException: com.test.bean.FunctionAccess
at com.thoughtworks.xstream.mapper.DefaultMapper.realClass(DefaultMapper.java:56) ~[xstream-1.4.2.jar:na]
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30) ~[xstream-1.4.2.jar:na]
at com.thoughtworks.xstream.mapper.DynamicProxyMapper.realClass(DynamicProxyMapper.java:55) ~[xstream-1.4.2.jar:na]
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30) ~[xstream-1.4.2.jar:na]
at com.thoughtworks.xstream.mapper.PackageAliasingMapper.realClass(PackageAliasingMapper.java:88) ~[xstream-1.4.2.jar:na]
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30) ~[xstream-1.4.2.jar:na]
at com.thoughtworks.xstream.mapper.ClassAliasingMapper.realClass(ClassAliasingMapper.java:79) ~[xstream-1.4.2.jar:na]
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30) ~[xstream-1.4.2.jar:na]
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30) ~[xstream-1.4.2.jar:na]
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30) ~[xstream-1.4.2.jar:na]
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30) ~[xstream-1.4.2.jar:na]
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30) ~[xstream-1.4.2.jar:na]
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30) ~[xstream-1.4.2.jar:na]
at com.thoughtworks.xstream.mapper.ArrayMapper.realClass(ArrayMapper.java:74) ~[xstream-1.4.2.jar:na]
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30) ~[xstream-1.4.2.jar:na]
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30) ~[xstream-1.4.2.jar:na]
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30) ~[xstream-1.4.2.jar:na]
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30) ~[xstream-1.4.2.jar:na]
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30) ~[xstream-1.4.2.jar:na]
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30) ~[xstream-1.4.2.jar:na]
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30) ~[xstream-1.4.2.jar:na]
at com.thoughtworks.xstream.mapper.CachingMapper.realClass(CachingMapper.java:45) ~[xstream-1.4.2.jar:na]
at com.thoughtworks.xstream.core.util.HierarchicalStreams.readClassType(HierarchicalStreams.java:29) ~[xstream-1.4.2.jar:na]
at com.thoughtworks.xstream.converters.collections.AbstractCollectionConverter.readItem(AbstractCollectionConverter.java:70) ~[xstream-1.4.2.jar:na]
at com.thoughtworks.xstream.converters.collections.CollectionConverter.addCurrentElementToCollection(CollectionConverter.java:79) ~[xstream-1.4.2.jar:na]
at com.thoughtworks.xstream.converters.collections.CollectionConverter.populateCollection(CollectionConverter.java:72) ~[xstream-1.4.2.jar:na]
at com.thoughtworks.xstream.converters.collections.CollectionConverter.populateCollection(CollectionConverter.java:66) ~[xstream-1.4.2.jar:na]
at com.thoughtworks.xstream.converters.collections.CollectionConverter.unmarshal(CollectionConverter.java:61) ~[xstream-1.4.2.jar:na]
at com.thoughtworks.xstream.core.TreeUnmarshaller.convert(TreeUnmarshaller.java:72) ~[xstream-1.4.2.jar:na]
先检查了代码,各种注解和生成的xml对比,确定代码没有问题。
然后反编译导出的jar包,看导出的jar包是否有问题,确认导出的jar包完整。
找度娘试了各种方法也没找到原因,最后只能去看源码了。
最终定位到xstream的DefaultMapper类的realClass方法。
public Class realClass(String elementName)
{
try
{
if(elementName.startsWith(XSTREAM_PACKAGE_ROOT))
return com/thoughtworks/xstream/mapper/DefaultMapper.getClassLoader().loadClass(elementName);
}
catch(ClassNotFoundException e)
{
throw new CannotResolveClassException(elementName);
}
if(elementName.charAt(0) != '[')
return classLoader.loadClass(elementName);
if(elementName.endsWith(";"))
return Class.forName(elementName.toString(),false,classLoader);
return Class.forName(elementName.toString());
}
查看源码后发现CannotResolveClassException异常实际是一个ClassNotFoundException异常,于是开始查找为什么找不到类,反编译后查看类是存在的。于是找xstream jar包,最终发现该包被产品组放到另一个jar包的lib目录里面。
这下就大概猜到原因了,可能是因为jar包中lib目录的jar里面的类调用Class.getClassLoader().loadClass(elementName);时会找不到外部jar写的java对象。
最终把xstream需要的几个jar包从产品的jar包中取出,正常运行,真是奇葩的问题,浪费了我两天时间。
但是由于项目里面不能直接去改产品里面的jar,最终又换成了JAXB实现xml与java bean互转,就没存在上面的问题了。