Tomcat 9.0.80中org.eclipse.emf.common多版本冲突排除方案咨询
运行在Tomcat 9.0.80下的Web应用启动时抛出java.lang.SecurityException,栈跟踪显示同一包下类的签名信息不匹配。排查发现WEB-INF/lib目录存在两个版本的org.eclipse.emf.common jar包:
ls -l | grep org.eclipse.emf.common -rw-r----- 1 tomcat tomcat 375780 Jul 3 2023 org.eclipse.emf.common-2.18.0.jar -rw-r----- 1 tomcat tomcat 211682 Nov 30 14:57 org.eclipse.emf.common-2.6.0.jar
手动移除2.6.0版本后应用可正常启动,但通过mvn dependency:tree -Dverbose=true | grep org.eclipse.emf.common仅能查到2.18.0版本依赖,无法定位2.6.0的来源;尝试用dependencyManager指定2.18.0版本,lib目录仍存在两个jar包。求其他排除无效jar包的方法。
异常栈跟踪:
Caused by: java.lang.SecurityException: class "org.eclipse.emf.common.notify.impl.BasicNotifierImpl$EScannableAdapterList"'s signer information does not match signer information of other classes in the same package at java.lang.ClassLoader.checkCerts(ClassLoader.java:891) at java.lang.ClassLoader.preDefineClass(ClassLoader.java:661) at java.lang.ClassLoader.defineClass(ClassLoader.java:754) at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) at org.apache.catalina.loader.WebappClassLoaderBase.findClassInternal(WebappClassLoaderBase.java:2337) at org.apache.catalina.loader.WebappClassLoaderBase.findClass(WebappClassLoaderBase.java:810) at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1293) at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1141) at java.lang.ClassLoader.defineClass1(Native Method) at java.lang.ClassLoader.defineClass(ClassLoader.java:756) at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) at org.apache.catalina.loader.WebappClassLoaderBase.findClassInternal(WebappClassLoaderBase.java:2337) at org.apache.catalina.loader.WebappClassLoaderBase.findClass(WebappClassLoaderBase.java:810) at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1293) at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1141) at org.eclipse.emf.ecore.impl.MinimalEObjectImpl.eAdapters(MinimalEObjectImpl.java:597) at org.eclipse.emf.ecore.impl.EClassImpl.getESuperAdapter(EClassImpl.java:2227) at org.eclipse.emf.ecore.impl.EClassImpl.getESuperTypes(EClassImpl.java:1714) at org.eclipse.emf.ecore.impl.EcorePackageImpl.initializePackageContents(EcorePackageImpl.java:2530) at org.eclipse.emf.ecore.impl.EcorePackageImpl.init(EcorePackageImpl.java:486) at org.eclipse.emf.ecore.EcorePackage.<clinit>(EcorePackage.java:67)
以下是几种定位并排除无效jar包的可行方案:
检查项目手动添加的jar包:
部分项目会直接将jar包放在src/main/webapp/WEB-INF/lib目录下,这类依赖不会被Maven的dependency:tree扫描到。直接检查该目录,手动删除2.6.0版本的jar包,同时确认后续不会被误加入。排查Maven打包插件配置:
像maven-war-plugin、assembly-plugin这类打包插件,可能通过<webResources>或自定义依赖集引入额外jar包。检查pom.xml中的插件配置,确认是否有节点引入了2.6.0版本的org.eclipse.emf.common。用Maven依赖分析工具深挖:
执行mvn dependency:analyze -Dverbose命令,查看所有直接、间接依赖的详细信息;或者执行mvn dependency:list -DincludeGroupIds=org.eclipse.emf,精准筛选该组下的所有依赖版本,确认2.6.0是否隐藏在某个依赖中。清理本地Maven仓库缓存:
本地仓库可能缓存了旧版本依赖,导致打包时被误引入。找到本地仓库中org/eclipse/emf/common目录,删除2.6.0版本的文件夹,再执行mvn clean package重新打包。强制锁定版本并排除旧依赖:
在pom.xml的dependencyManagement中明确锁定2.18.0版本,同时在所有可能引入该依赖的直接依赖中添加排除规则:<dependencyManagement> <dependencies> <dependency> <groupId>org.eclipse.emf</groupId> <artifactId>org.eclipse.emf.common</artifactId> <version>2.18.0</version> </dependency> </dependencies> </dependencyManagement> <dependencies> <!-- 示例:对所有包含该依赖的直接依赖添加排除 --> <dependency> <groupId>[依赖组ID]</groupId> <artifactId>[依赖 artifactID]</artifactId> <exclusions> <exclusion> <groupId>org.eclipse.emf</groupId> <artifactId>org.eclipse.emf.common</artifactId> </exclusion> </exclusions> </dependency> </dependencies>检查Tomcat全局lib目录:
确认Tomcat的CATALINA_HOME/lib或CATALINA_BASE/lib目录下是否存在2.6.0版本的jar包,如果有,删除该jar包,避免Web应用加载全局旧版本依赖。
内容的提问来源于stack exchange,提问作者Ubuntu Learner

