最近某Java工程启动中抛出了一个诡异的问题, 堆栈比较长, 主要缘由是:java
java.lang.SecurityException: class "javax.servlet.AsyncListener"'s signer information does not match signer information of other classes in the same package
经Google, 发现是因为javax.servlet这个包中的众多类, 在多个Jar包中均有实现(好比X和Y都有实现), 若是该Java进程加载时, 使用了X.jar中的javax.servlet.A, 又加载了Y.jar中的javax.servlet.B, 同时X.jar和Y.jar的签名不一致, 这样会致使以上报错.api
在IDE中查找类javax.servlet.AsyncListener
, 发如今多个带javaee或者servlet名字的jar包中均有实现, 能够经过如下命令获取工程的全部依赖:tomcat
mvn dependency:tree
为了定位是哪一个Jar包致使的该问题, 咱们在实现了这个类的Jar包中, 进行签名检查:eclipse
jarsigner -verify xxx.jar
经过这个命令能够看到该Jar是否有签名. ide
最后发现, 这些Jar包中, 只有一个有签名, 而其余都没有:code
org.eclipse.jetty.orbit:javax.servlet:jar:3.0.0.v201112011016:compile
因此能够推断应该是这个eclipse对servlet的实现的Jar包使用了签名, 致使和其余相关Jar包不兼容. (是有多喜欢造轮子)orm
而这个Jar包, 经过依赖树, 咱们发现是hive-jdbc 2.3.2依赖引入的(看着hive依赖真混乱..., 记得hbase也是), 经过升级到 3.1.0, 再次检查依赖, 咱们发现这个Jar包已经不在依赖树中了. 而启动错误也消失了.进程
或者还有另一个方法, 把这个有问题的包从hive-jdbc 2.3.2 中exlucde掉, 让hive使用其余包中的javax.servlet
实现. 其实即使没有其余包有javax.servlet
的实现, 或者其scope为provided, 只要这个工程在tomcat中启动, 都是能够的. 由于tomcat自带servlet-api
实现.ip