WebSphere 8.5.5中SolrJ-7.0.0重启后触发LinkageError问题咨询
看你贴的异常堆栈,这个坑我之前在WebSphere上踩过!核心就是类加载器的命名空间冲突:SolrJ里ZkStateReader生成的Lambda类用的是JDK自带的InternalAnonymousClassLoader,但WebSphere加载Zookeeper的Watcher接口用的是它自己的CompoundClassLoader,JVM不认这俩加载器下的Watcher是同一个类型,结果Lambda实现接口的时候就报方法签名不匹配的加载约束错误了。
为啥会出这问题?
- WebSphere的类加载器层级本来就复杂,它的
CompoundClassLoader默认会先从服务器层面找类,再加载应用里的 - SolrJ运行时生成的Lambda类是JDK动态创建的,用的是专门的匿名类加载器
- 这俩加载器的命名空间是隔离的,导致JVM判定
Watcher接口不是同一个类型,自然就冲突了
给你几个靠谱的解决办法
办法1:让应用优先加载自己的依赖(最常用)
WebSphere允许修改类加载顺序,强制应用先加载自己打包的Jar,不用服务器层面的:
- 登录WebSphere控制台,找到你的应用
- 进入应用程序 > 你的应用 > 类加载和更新检测
- 将类加载顺序设置为
类加载器的父类最后(Parent Last) - 如果是WAR包,把WAR类加载器策略设为
应用程序 - 保存配置后重启应用
办法2:排除WebSphere自带的Zookeeper类(如果存在)
有些WebSphere环境因为安装了扩展组件可能自带Zookeeper,得让应用强制用自己打包的版本:
- 在应用的
WEB-INF目录下创建(或修改)ibm-web-ext.xml文件 - 添加以下配置:
<?xml version="1.0" encoding="UTF-8"?> <web-ext xmlns="http://websphere.ibm.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://websphere.ibm.com/xml/ns/javaee http://websphere.ibm.com/xml/ns/javaee/ibm-web-ext_1_0.xsd" version="1.0"> <classloader mode="PARENT_LAST"/> <exclusion href="*"> <filter-exclude filter-name="org/apache/zookeeper/**"/> </exclusion> </web-ext>
这个配置的作用是告诉WebSphere,不要加载服务器层面的Zookeeper相关类,完全使用应用自身打包的版本。
办法3:升级SolrJ版本试试
SolrJ 7.0的Zookeeper依赖可能和WebSphere的类加载环境兼容性不佳,试试升级到7.x系列的稳定版本(比如7.7.3),这个版本对类加载相关的问题修复较多,同时也能兼容Solr 7服务器。
办法4:临时禁用Lambda生成(应急用)
如果上面的办法一时半会儿无法生效,可以先通过JVM参数临时绕过:
在WebSphere的JVM参数中添加:
-Djdk.internal.lambda.dumpProxyClasses=false -Djava.lang.invoke.LambdaMetafactory.enable=false
这个参数会让JVM用匿名内部类替代Lambda表达式生成,不过可能影响其他使用Lambda的代码,仅作为临时救急方案,不建议长期使用。
验证步骤
修改配置并重启服务器后,触发之前抛出异常的操作,检查是否还会出现LinkageError。也可以查看应用日志,确认Zookeeper相关类是否由应用自身的类加载器加载。
内容的提问来源于stack exchange,提问作者tester

