最近某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