使用dom4j发现的一个问题

本文探讨了使用DOM4J时遇到的ClassCastException问题,解析了问题产生的原因在于同一类被不同类加载器加载,并提供了三种解决方案:统一DOM4J版本、显式设置DocumentFactory实例以及改进DOM4J的加载机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在使用dom4j时碰到一个ClassCastException问题:org.dom4j.DocumentFactory不能转换为org.dom4j.DocumentFactory。

同一个类不能相互转换,一般是由于这是两个分别由不同类加载器加载的类的缘故。

检查发现,在一个webapp下和tomcat的shared目录下均存在dom4j的包,因此这两个类应该是分别从这两个包中加载的。

为什么会从两个地方的jar包分别加载同一个类呢?这有点奇怪,于是看了下dom4j的源码,发现问题在DocumentFactory的加载机制上。

DocumentFactory的实现类可以由用户自己指定,因此程序中选择通过ContextClassLoader进行加载,这是合理的,用户指定的类应该是可以通过当前线程的加载器加载。

问题出在:在share中的一个类使用到了dom4j,于是share加载了dom4j中的所有类。

而ContextClassLoader是webapp加载器,于是又从webapp中加载了一次DocumentFactory,并创建实现。

该实现再使用显示转换成share所加载的DocumentFactory类的实例,这样就发生异常了。

 

解决方法:

1.当然是只在一个地方放置dom4j的包。

2.这种情况不能完全避免,因此也可以在使用dom4j是显示地设置DocumentFactory实例,这样程序就不会再去加载该类了。

3.其实dom4j本身也可以改进一下,检查到用户指定的类以org.dom4j.开头则由当前加载器加载,其他的才通过ContextClassLoader进行加载。

 

扩展:

在程序中使用到ContextClassLoader加载类的地方也都最好进行检查,如果属于本jar包中的类则改用当前加载器加载。

 

转载于:https://www.cnblogs.com/goodjin/archive/2012/05/12/2497146.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值