這篇文章主要介紹了Java類加載器與類沖突怎么解決的相關(guān)知識(shí),內(nèi)容詳細(xì)易懂,操作簡單快捷,具有一定借鑒價(jià)值,相信大家閱讀完這篇Java類加載器與類沖突怎么解決文章都會(huì)有所收獲,下面我們一起來看看吧。
成都網(wǎng)絡(luò)公司-成都網(wǎng)站建設(shè)公司成都創(chuàng)新互聯(lián)公司十年經(jīng)驗(yàn)成就非凡,專業(yè)從事做網(wǎng)站、成都網(wǎng)站制作,成都網(wǎng)頁設(shè)計(jì),成都網(wǎng)頁制作,軟文推廣,廣告投放等。十年來已成功提供全面的成都網(wǎng)站建設(shè)方案,打造行業(yè)特色的成都網(wǎng)站建設(shè)案例,建站熱線:13518219792,我們期待您的來電!
在同一個(gè)項(xiàng)目中,包含了一個(gè)類庫的兩個(gè)不同版本
這個(gè)時(shí)候,可能就會(huì)遇到奇怪的問題
代碼的邏輯不符合預(yù)期
出現(xiàn)NoSuchMethodError
...
先說結(jié)論,出現(xiàn)這些問題,不用懷疑,一定是當(dāng)前使用的class版本和你預(yù)期的不一致。
這里我們以 apache 的 commons-codec類庫來分析問題場景。
在實(shí)現(xiàn)一個(gè)功能的時(shí)候,你通過maven引入了這個(gè)庫的依賴:
commons-codec
commons-codec
1.10
此時(shí),在代碼里使用了類庫內(nèi)處理Base64的一個(gè)類,有一個(gè)這樣的實(shí)現(xiàn)
public static byte[] decodeBase64(String base64String) {
return (new Base64()).decode(base64String);
}
然后沒多久,系統(tǒng)中新增其它的功能,和其他系統(tǒng)對接的時(shí)候,引入了一個(gè)依賴。當(dāng)我們高高興興的完成了任務(wù),提交代碼時(shí),某天會(huì)遇到QA提了一個(gè)問題,XX功能現(xiàn)在不可用。
什么情況,WTF?
然后重跑功能,果不其然。什么情況。原來我們之前使用的commons-codec-1.10版本,并沒有被使用,而是使用了com.springsource.org.apache.commons.codec-1.3.0版本。
什么情況?
我們在接入其他系統(tǒng)的時(shí)候,引入了一些依賴,而這其中他會(huì)依賴一個(gè)
org.apache.commons
com.springsource.org.apache.commons.httpclient
而他,會(huì)把上面的com.springsource.org.apache.commons.codec-1.3.0引進(jìn)來。
此時(shí),系統(tǒng)中就會(huì)有兩個(gè)關(guān)于commons-codec的包。
而舊版本的對應(yīng)Base64的類,只支持傳入一個(gè)數(shù)組,不支持String
難道Maven這么傻,不會(huì)解決一下?
他會(huì)根據(jù)引入的版本,使用的maven的版本,從而選擇是根據(jù)依賴聲明的前后順序或者是nearest來使用。但這個(gè)解決不了我們上面的問題,因?yàn)閙aven對于同一個(gè)groupId和artifactId才會(huì)使用上面這個(gè)依賴機(jī)制,所以相同的groupId和artifactId的依賴,會(huì)直接忽略,最終只使用一個(gè)。依賴樹上可以看了出來:
看上面的提示omitted for duplicate。而上面關(guān)于codec的依賴,是因?yàn)閍rtifactId被換成了org.springsource.org.apache.commons,這樣maven的機(jī)制就不會(huì)生效,導(dǎo)致項(xiàng)目里出現(xiàn)了兩個(gè)codec的jar。而且,codec.jar雖然對于org.springsource這個(gè)指定的,雖然artifactId是這個(gè),但里面的包名還是一樣樣的org.apache.commons,所以是相同于兩個(gè)一模一樣的Jar,只是版本不同。
這個(gè)時(shí)候,到了類加載器上場的時(shí)候了。類加載器在加載類,初始化的時(shí)候,會(huì)需要加載當(dāng)前class依賴的類,此時(shí),由于依賴低版本codec的class先被加載,從而導(dǎo)致低版本的codec被加載。
等后面再需要codec的地方又需要類的時(shí)候,此時(shí)雖然WebappClassloader可以子優(yōu)先加載,對于不同的應(yīng)用進(jìn)行資源隔離,但是對于同一個(gè)應(yīng)用內(nèi)的相同package的類,是不會(huì)重復(fù)加載的。此時(shí),有相同的請求到來時(shí),從已經(jīng)加載的資源中找到了低版本的codec,就直接用了,而這個(gè)類里沒有我們要調(diào)用的方法,就出現(xiàn)了熟悉的NoSuchMethodError。
解決
問題了解清楚了,那該怎么解決呢,引入一個(gè)依賴的時(shí)候,總不能一個(gè)個(gè)的去查看jar的pom聲明。
出現(xiàn)了上述問題時(shí),如果不是使用maven管理依賴的,像之前SSH那種一下添加一堆jar到lib目錄的時(shí)候,確定了對應(yīng)的問題jar后,直接刪除就好,簡單直接。
如果是用maven管理依賴,就需要了解,是請把這小子帶到這兒的。這個(gè)時(shí)候,使用maven的命令工具:
mvn dependency:tree
然后把結(jié)果生成到一個(gè)文件中,就可以查看引入沖突的jar是誰引進(jìn)來的,查明真相后,就把依賴排除出去,
類似這樣:
com.xxx
xxx
1.0.4
org.apache.commons
com.springsource.org.apache.commons.codec
關(guān)于“Java類加載器與類沖突怎么解決”這篇文章的內(nèi)容就介紹到這里,感謝各位的閱讀!相信大家對“Java類加載器與類沖突怎么解決”知識(shí)都有一定的了解,大家如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。