应用业务代码升级log4j2 的jcl-over-slf4j-1.7.36.jar 与 WebSphere容器中间件依赖的com.ibm.ws.xx.commons-logging.jar类加载冲突
最终解决 在was新建共享库,新增: ${WAS_INSTALL_ROOT}/optionalLibraries/IBM/LOG4J2/2.0/com.ibm.ws.prereq.commons-logging.jar 包,需要勾选使用隔离类加载器加载

报错:Caused by: org.apache.commons.discovery.DiscoveryException: Class org.apache.commons.logging.impl.LogFactoryImpl does not implement org.apache.commons.logging.LogFactory at org.apache.commons.discovery.tools.ClassUtils.verifyAncestory(ClassUtils.java:180) ~[commons-discovery.jar:0.2] at org.apache.commons.discovery.tools.SPInterface.verifyAncestory(SPInterface.java:201) ~[commons-discovery.jar:0.2] at org.apache.commons.discovery.tools.SPInterface.newInstance(SPInterface.java:195) ~[commons-discovery.jar:0.2] at org.apache.commons.discovery.tools.DiscoverClass.newInstance(DiscoverClass.java:579) ~[commons-discovery.jar:0.2] at org.apache.commons.discovery.tools.DiscoverSingleton.find(DiscoverSingleton.java:418) ~[commons-discovery.jar:0.2] at org.apache.commons.discovery.tools.DiscoverSingleton.find(DiscoverSingleton.java:320) ~[commons-discovery.jar:0.2] at org.apache.axis.components.logger.LogFactory$1.run(LogFactory.java:59) ~[axis.jar:?] at java.security.AccessController.doPrivileged(AccessController.java:647) ~[?:1.8.0] at org.apache.axis.components.logger.LogFactory.getLogFactory(LogFactory.java:42) ~[axis.jar:?] at org.apache.axis.components.logger.LogFactory.<clinit>(LogFactory.java:34) ~[axis.jar:?] at org.apache.axis.handlers.BasicHandler.<clinit>(BasicHandler.java:43) ~[axis.jar:?] at org.apache.axis.client.Service.getAxisClient(Service.java:104) ~[axis.jar:?] at org.apache.axis.client.Service.<init>(Service.java:113) ~[axis.jar:?]
猜测引发冲突的axis.jar包 依赖的com.ibm.ws.prereq.commons-logging.jar(org.apache.commons.logging.impl.LogFactoryImpl) 是由父类加载器加载的,而 jcl-over-slf4j-1.7.36.jar(org.apache.commons.logging.LogFactory)接口由web模块类加载器加载的 ,不同的类加载器加载的 LogFactoryImpl 和 LogFactory 被认为是不同类型的。
axis.jar 包通过 commons-discovery 去查找加载 org.apache.commons.logging.LogFactory 并返回具体的实现类(org.apache.commons.logging.impl.LogFactoryImpl)对象,
在commons-discovery.jar包的find方法中 加载(利用了多个类加载器去加载类且was默认是parent first 父类优先)到了类路径中 LogFactory和 LogFactoryImpl 在校验时发现 这两个类来自不同名字不同路径的jar包,由不同的类加载器加载
服务器排除问题,调试策略:
--由于was 本地没法运行调试,只能通过在github仓库获取discovery.jar包源码重新编译,在报错的代码位置增加输出语句,输出冲突的两个jar包路径
两个冲突的依赖包位置
1.
location:org.apache.commons.logging.LogFactory from file:/opt/ibm/WebSphere/ProcServer/optionalLibraries/IBM/LOG4J2/2.0/jcl-over-slf4j-1.7.36.jar
2.
location:org.apache.commons.logging.impl.LogFactoryImpl from file:/opt/ibm/WebSphere/ProcServer/plugins/com.ibm.ws.prereq.commons-logging.jar
设置共享库的目的是
将 com.ibm.ws.xx.commons-logging.jar ,和 jcl-over-slf4j-1.7.36.jar 强制使用同一个类加载器 去加载,只要保证org.apache.commons.logging.impl.LogFactoryImpl 和 org.apache.commons.logging.LogFactory 由同一个 类加载器(相同命名空间)去加载的 就不会导致类加载冲突
共享库,只是设置独立类加载器 加载 jar包位置,真正使用到共享库中的某个类时再由业务调用触发这个类加载器去加载这两个jar包
问题反思:
在axis.jar包中,使用到的 org.apache.commons.logging.impl.LogFactoryImpl (/opt/ibm/WebSphere/ProcServer/plugins/com.ibm.ws.prereq.commons-logging.jar )为什么会被 父类加载器加载(应用下也存在commons-logging-1.1.jar)?因为父类优先?那我设置共享库之后能解决问题,就是以共享库优先加载?
更多推荐
所有评论(0)