Oracle WebLogic 12c中ClassCastException类加载异常问题求助
解决WebLogic 12c多EAR部署下的ClassCastException(疑似类加载问题)
听起来你遇到的这个ClassCastException十有八九是WebLogic的类加载器隔离机制搞的鬼——毕竟你两个EAR里都打包了相同的JAR包,而WebLogic默认会给每个EAR分配独立的类加载器,这就导致同一个类(比如你的DAO、JPA实体或者EJB类)被加载了两次,变成了两个完全不同的类实例,互相转换自然就会抛异常。
下面给你几个针对性的解决方案和排查思路:
一、最推荐的方案:把共享JAR部署为WebLogic共享库(Shared Library)
这是WebLogic官方推荐的多应用共享代码的方式,能从根源上解决类加载重复的问题:
- 改造共享JAR为共享库
在你的共享JAR的MANIFEST.MF文件中添加以下属性(可以用Maven的maven-jar-plugin配置自动生成):
这里的Extension-Name: com.yourcompany.shared.persistence Specification-Version: 1.0 Implementation-Version: 1.0.0Extension-Name是共享库的唯一标识,后面两个版本号用来做版本管理。 - 部署共享库到WebLogic
把改造后的JAR上传到WebLogic控制台,选择"部署"->"安装",在部署类型里选择"库",完成部署。 - 让两个EAR引用这个共享库
在每个EAR的META-INF/MANIFEST.MF中添加以下配置,声明依赖这个共享库:
这样两个EAR就会使用共享库的类加载器来加载这个JAR里的类,不会再各自重复加载了。Extension-List: sharedpersistence sharedpersistence-Extension-Name: com.yourcompany.shared.persistence sharedpersistence-Specification-Version: 1.0
二、备选方案:调整类加载策略
如果暂时不想改造成共享库,也可以通过调整WebLogic的类加载规则来解决:
- 把共享JAR放到Domain级别的lib目录
把你的共享JAR复制到WebLogic域的domain/lib目录下,WebLogic的系统类加载器会加载这个JAR,两个EAR都会使用父类加载器加载的类,避免重复。不过这种方式灵活性差,后续升级共享JAR需要重启整个域。 - 修改EAR的类加载模式为父优先
在WebLogic控制台找到每个EAR的部署配置,在"类加载"选项里,把默认的"Parent Last"(子优先,先加载自己EAR里的类)改成"Parent First"(父优先,先找系统/共享类加载器的类)。不过要注意这种方式可能会和WebLogic自带的类产生冲突,需要测试验证。
三、排查确认是否真的是类加载问题
可以用以下方法快速验证:
- 在代码中打印类加载器信息
在你的DAO或者EJB类里加一行代码:
分别启动两个应用,查看日志,如果两个应用打印的类加载器实例不同(比如System.out.println("类加载器信息:" + YourEntity.class.getClassLoader());weblogic.utils.classloaders.ChangeAwareClassLoader@xxxx这种格式的对象哈希不同),就确认是类加载重复导致的问题。 - 开启WebLogic类加载调试日志
在WebLogic控制台的日志配置里,把weblogic.classloader的日志级别改成Debug,启动应用后查看日志,可以清楚看到每个类是被哪个类加载器加载的,以及加载的来源路径。
四、额外注意事项
- 如果你的共享JAR里包含JPA实体类,要确保
persistence.xml的配置一致,最好把persistence.xml也放到共享库中,避免两个EAR里的配置冲突。 - 如果你用了EJB,要确保共享库中的无状态会话Bean被正确暴露,两个EAR可以通过JNDI正常查找引用。
内容的提问来源于stack exchange,提问作者lftl
相关产品推荐
相关产品推荐

