下面舉一個包衝突的例子:java
你引用了 2 個三方包 a.jar 和 b.jar , a.jar 中又引用了一個 c.jar ,假設 c.jar 的版本號爲 version-1, b.jar 中也引用了 c.jar ,假設這裏的 c.jar 相對於 a.jar 中的 c.jar 爲較高版本,記爲 version-2 , b.jar 中某個類引用了 c.jar 的類 classA 中的方法 method A() ,而且該方法只存在於高版本的 c.jar(version-2) 的類 classA 中,而不存在c.jar(version-1) 的類 classA 中。eclipse
當系統編譯加載時,系統可能編譯加載 c.jar(version-1) ,也可能編譯加載 c.jar(version-2) ,當編譯加載c.jar(version-2) 時,因爲不少 jar 包都支持向下兼容,即高版本兼容低版本,所以不論 a.jar 調用 c.jar 仍是 b.jar 調用 c.jar 通常都不會出問題。但若是此時恰好應用編譯加載的是 c.jar(version-1) 中的類 classA 時,那麼 b.jar 調用Method A() 時便會報上述錯誤,由於 Method A() 函數只存在於高版本的 c.jar 中,而此時系統編譯加載的倒是低版本的 c.jar 。jvm
jar包衝突常見的異常爲找不到類(java.lang.ClassNotFoundException)、找不到具體方法(java.lang.NoSuchMethodError)、字段錯誤( java.lang.NoSuchFieldError)或者類錯誤(java.lang.LinkageError)。maven
常見的解決方法以下:ide
一、首先作法是打出工程文件的依賴樹,將根據jar包依賴狀況斷定是否是同一個jar包依賴了多個版本,若是確認問題所在,直接exclusion其中錯誤的jar包便可;函數
二、若是經過看依賴樹不能肯定具體衝突的jar包,可使用添加jvm參數的方式啓動程序,將類加載的具體jar信息打印出來;-verbose:class;google
三、通過上述步驟基本就能夠解決jar包衝突問題,具體的問題要具體分析,當問題不可重現時上述方法均不會奏效。idea
排包方法:spa
<dependency> <groupId>com.know.diamond</groupId> <artifactId>diamond-sdk</artifactId> <version>2.0.5</version> <exclusions> <exclusion> <groupId>com.google.collections</groupId> <artifactId>google-collections</artifactId> </exclusion> </exclusions> </dependency>
當遇到jar包衝突時,咱們首先肯定是哪一個jar包衝突了,這個很容易,看咱們調用的類或方法,是屬於哪一個Jar包。而後就是要找出衝突了,我這裏使用命令code
mvn dependency:tree -Dverbose -Dincludes=<groupId>:<artifactId>
填寫上Jar包的groupId和artifactId,能夠只有一個,可是中間的冒號不要少,這樣就會輸出依賴樹,並且是僅包含這個Jar包的依賴樹,這樣那些地方依賴了這個Jar包的那個版本就一目瞭然了。
例如,個人項目中notify-common包存在衝突,咱們使用命令mvn dependency:tree -Dverbose -Dincludes=:notify-common
獲得依賴樹輸出
[INFO] com.taobao.wlb:bis-server:war:1.0-SNAPSHOT
[INFO] +- com.taobao.wlb:bis-core:jar:1.0-SNAPSHOT:compile
[INFO] | \- com.taobao.logistics:schedule-client:jar:1.1.1:compile
[INFO] | \- (com.taobao.notify:notify-common:jar:1.8.15:compile - omitted for conflict with 1.8.19.26)
[INFO] \- com.taobao.notify:notify-tr-client:jar:1.8.19.26:compile
[INFO] +- com.taobao.notify:notify-common:jar:1.8.19.26:compile
[INFO] \- com.taobao.notify:notify-remoting:jar:1.8.19.26:compile
[INFO] \- (com.taobao.notify:notify-common:jar:1.8.19.26:compile - omitted for duplicate)
看一下依賴樹中全部的葉子節點就是全部的notify-common包,咱們能夠看到咱們依賴的bis-core中依賴了schedule-client包,它依賴了一個notify-common包,版本是1.8.15,第四行的後面也提示了這個包同其餘包有衝突- omitted for conflict with 1.8.19.26)
。而咱們的系統依賴的notify-tr-client包所依賴的版本是1.8.19.26,因而咱們知道是這裏衝突了,在POM排除掉依賴,OK了。
這裏咱們對咱們執行的命令作一個簡單的說明。mvn dependency:tree -Dverbose -Dincludes=<groupId>:<artifactId>
第一部分mvn dependency:tree
是maven依賴的分析命令,做用是對咱們的項目的依賴進行分析,並輸出項目依賴樹。
第二部分-Dverbose
的做用是添加了verbose一個環境變量,起的做用是在分析項目依賴時輸出明細,這樣項目中依賴的全部引用都會被輸出出來,包含了全部的間接引用,會有不少不少,咱們只須要咱們要找的,因此就須要第三個參數了。
第三部分-Dincludes=<groupId>:<artifactId>
的做用就是進行過濾,只包含咱們想要的依賴的依賴時,排除掉其它不須要的,依賴樹的全部葉子節點就是咱們的找的依賴包。其中的groupId和artifactId能夠只填寫一個,爲了保證準確性,通常都會填兩個(填寫時不包括尖括號)。
其餘方法:
一、對於maven工程,個人辦法是使用eclipse來解決,點開pom.xml,切換到hierarchy dependency,右上角搜索對應的包,能夠清晰地看到衝突版本
二、可使用idea,在pom.xml中右單擊 選擇Diagrams-》show dependencies
三、mvn dependency:tree -Dverbose > tree.log 直接輸出衝突的jar文件