您好,登錄后才能下訂單哦!
這篇文章主要介紹了Java類加載器與類沖突怎么解決的相關知識,內容詳細易懂,操作簡單快捷,具有一定借鑒價值,相信大家閱讀完這篇Java類加載器與類沖突怎么解決文章都會有所收獲,下面我們一起來看看吧。
在同一個項目中,包含了一個類庫的兩個不同版本
這個時候,可能就會遇到奇怪的問題
代碼的邏輯不符合預期
出現NoSuchMethodError
...
先說結論,出現這些問題,不用懷疑,一定是當前使用的class版本和你預期的不一致。
這里我們以 apache 的 commons-codec類庫來分析問題場景。
在實現一個功能的時候,你通過maven引入了這個庫的依賴:
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.10</version>
</dependency>
此時,在代碼里使用了類庫內處理Base64的一個類,有一個這樣的實現
public static byte[] decodeBase64(String base64String) {
return (new Base64()).decode(base64String);
}
然后沒多久,系統中新增其它的功能,和其他系統對接的時候,引入了一個依賴。當我們高高興興的完成了任務,提交代碼時,某天會遇到QA提了一個問題,XX功能現在不可用。
什么情況,WTF?
然后重跑功能,果不其然。什么情況。原來我們之前使用的commons-codec-1.10版本,并沒有被使用,而是使用了com.springsource.org.apache.commons.codec-1.3.0版本。
什么情況?
我們在接入其他系統的時候,引入了一些依賴,而這其中他會依賴一個
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>com.springsource.org.apache.commons.httpclient</artifactId>
</dependency>
而他,會把上面的com.springsource.org.apache.commons.codec-1.3.0引進來。
此時,系統中就會有兩個關于commons-codec的包。
而舊版本的對應Base64的類,只支持傳入一個數組,不支持String
難道Maven這么傻,不會解決一下?
他會根據引入的版本,使用的maven的版本,從而選擇是根據依賴聲明的前后順序或者是nearest來使用。但這個解決不了我們上面的問題,因為maven對于同一個groupId和artifactId才會使用上面這個依賴機制,所以相同的groupId和artifactId的依賴,會直接忽略,最終只使用一個。依賴樹上可以看了出來:
看上面的提示omitted for duplicate。而上面關于codec的依賴,是因為artifactId被換成了org.springsource.org.apache.commons,這樣maven的機制就不會生效,導致項目里出現了兩個codec的jar。而且,codec.jar雖然對于org.springsource這個指定的,雖然artifactId是這個,但里面的包名還是一樣樣的org.apache.commons,所以是相同于兩個一模一樣的Jar,只是版本不同。
這個時候,到了類加載器上場的時候了。類加載器在加載類,初始化的時候,會需要加載當前class依賴的類,此時,由于依賴低版本codec的class先被加載,從而導致低版本的codec被加載。
等后面再需要codec的地方又需要類的時候,此時雖然WebappClassloader可以子優先加載,對于不同的應用進行資源隔離,但是對于同一個應用內的相同package的類,是不會重復加載的。此時,有相同的請求到來時,從已經加載的資源中找到了低版本的codec,就直接用了,而這個類里沒有我們要調用的方法,就出現了熟悉的NoSuchMethodError。
解決
問題了解清楚了,那該怎么解決呢,引入一個依賴的時候,總不能一個個的去查看jar的pom聲明。
出現了上述問題時,如果不是使用maven管理依賴的,像之前SSH那種一下添加一堆jar到lib目錄的時候,確定了對應的問題jar后,直接刪除就好,簡單直接。
如果是用maven管理依賴,就需要了解,是請把這小子帶到這兒的。這個時候,使用maven的命令工具:
mvn dependency:tree
然后把結果生成到一個文件中,就可以查看引入沖突的jar是誰引進來的,查明真相后,就把依賴排除出去,
類似這樣:
<dependency>
<groupId>com.xxx</groupId>
<artifactId>xxx</artifactId>
<version>1.0.4</version>
<exclusions>
<exclusion>
<groupId>org.apache.commons</groupId>
<artifactId>com.springsource.org.apache.commons.codec</artifactId>
</exclusion>
</exclusions>
</dependency>
關于“Java類加載器與類沖突怎么解決”這篇文章的內容就介紹到這里,感謝各位的閱讀!相信大家對“Java類加載器與類沖突怎么解決”知識都有一定的了解,大家如果還想學習更多知識,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。