JAR沖突問題的解決以及運(yùn)行狀態(tài)下如何查看加載的類

今天碰到群里小伙伴問,線上程序好像有多個(gè)不同版本的Netty包,怎么去看到底加載了哪一個(gè)?

在說如何看之前,先來說說,當(dāng)你開始意識到項(xiàng)目里有多個(gè)不同版本的Jar包,都是因?yàn)橛龅搅诉@幾個(gè)異常:

  1. java.lang.NoSuchMethodException:自己代碼中調(diào)用了某個(gè)方法,因?yàn)榧虞d了其他版本的jar,這個(gè)版本正好沒這個(gè)方法。
  2. java.lang.NoClassDefFoundError:編譯時(shí)候是好的,但是運(yùn)行的時(shí)候,因?yàn)榧虞d的jar版本問題,沒有這個(gè)類。
  3. java.lang.ClassNotFoundException:在動態(tài)加載某個(gè)Class的時(shí)候,因?yàn)橐虞d的jar不是正確的版本,而導(dǎo)致找不到這個(gè)類。

當(dāng)你在本地運(yùn)行ok,但到服務(wù)器上發(fā)現(xiàn)出現(xiàn)這些錯(cuò)誤的時(shí)候,就要意識到很可能是jar沖突了(有相同依賴存在多個(gè)版本)。這個(gè)問題往往也會有這樣的表現(xiàn):多實(shí)例部署的時(shí)候,有的實(shí)例是好的,有的實(shí)例則不行。

查看加載的類和方法

根據(jù)之前分析的異常種類,我們可以去運(yùn)行中的現(xiàn)場確認(rèn)當(dāng)前加載的問題。

這里我們可以使用阿里開源的Arthas工具,如果第一次用,那么按下面操作先安裝再運(yùn)行:

curl -O https://arthas.aliyun.com/arthas-boot.jar
java -jar arthas-boot.jar

運(yùn)行好之后,會打印出當(dāng)前運(yùn)行著的java應(yīng)用,比如:

[INFO] arthas-boot version: 3.4.6
[INFO] Process 40611 already using port 3658
[INFO] Process 40611 already using port 8563
[INFO] Found existing java process, please choose one and input the serial number of the process, eg : 1. Then hit ENTER.
* [1]: 40611 chapter4-3-0.0.1-SNAPSHOT.jar
  [2]: 37786

通過輸入編號選擇要查看的java應(yīng)用,比如這里選擇:1,進(jìn)入到chapter4-3-0.0.1-SNAPSHOT.jar中去。

下面介紹兩個(gè)重要命令:

第一個(gè):sc命令,我們確認(rèn)一下可能沖突的jar包下面,是否有對應(yīng)的class。有些不同版本包下class就不一樣,馬上就可以分辨出來。

比如,通過下面的命令,我們查看一下com.didispace包下有什么類:

[arthas@40611]$ sc com.didispace.*
com.didispace.chapter43.Chapter43Application
com.didispace.chapter43.Chapter43Application$$EnhancerBySpringCGLIB$$8b82b194
com.didispace.chapter43.UploadController
Affect(row-cnt:3) cost in 6 ms.

第二個(gè):sm命令,查看具體某個(gè)類有哪些方法。有的版本差異就是去掉了某個(gè)方法,這個(gè)時(shí)候我們就可以通過這個(gè)命令來查看。

比如,通過下面的命令,我們查看一下com.didispace.chapter43.UploadController類下有些什么方法:

[arthas@40611]$ sm com.didispace.chapter43.UploadController
com.didispace.chapter43.UploadController <init>()V
com.didispace.chapter43.UploadController create(Lorg/springframework/web/multipart/MultipartFile;)Ljava/lang/String;
com.didispace.chapter43.UploadController uploadPage()Ljava/lang/String;
Affect(row-cnt:3) cost in 5 ms.

本文首發(fā):https://blog.didispace.com/arthas-sc-and-sm

找到?jīng)_突并解決沖突

在確認(rèn)完是加載錯(cuò)誤的情況下,我們要去解決沖突。那么解決沖突要做的就是找到到底哪里沖突了以及我們要去除或者強(qiáng)制

找出版本沖突的方法:使用Maven命令:mvn -U dependency:tree -Dverbose。

命令執(zhí)行之后,會在控制臺以樹狀形式列出所有依賴內(nèi)容,然后通過搜索的方式查找沖突的包,看看都是從哪個(gè)依賴中帶進(jìn)來的(在IDEA中搜索會高亮,更容易找到)。

[INFO] com.didispace:chapter4-3:jar:0.0.1-SNAPSHOT
[INFO] +- org.springframework.boot:spring-boot-starter-web:jar:2.4.1:compile
[INFO] |  +- org.springframework.boot:spring-boot-starter:jar:2.4.1:compile
[INFO] |  |  +- org.springframework.boot:spring-boot:jar:2.4.1:compile
[INFO] |  |  +- org.springframework.boot:spring-boot-autoconfigure:jar:2.4.1:compile
[INFO] |  |  +- org.springframework.boot:spring-boot-starter-logging:jar:2.4.1:compile
[INFO] |  |  |  +- ch.qos.logback:logback-classic:jar:1.2.3:compile
[INFO] |  |  |  |  \- ch.qos.logback:logback-core:jar:1.2.3:compile
[INFO] |  |  |  +- org.apache.logging.log4j:log4j-to-slf4j:jar:2.13.3:compile
[INFO] |  |  |  |  \- org.apache.logging.log4j:log4j-api:jar:2.13.3:compile
[INFO] |  |  |  \- org.slf4j:jul-to-slf4j:jar:1.7.30:compile
[INFO] |  |  +- jakarta.annotation:jakarta.annotation-api:jar:1.3.5:compile
[INFO] |  |  \- org.yaml:snakeyaml:jar:1.27:compile
[INFO] |  +- org.springframework.boot:spring-boot-starter-json:jar:2.4.1:compile
[INFO] |  |  +- com.fasterxml.jackson.core:jackson-databind:jar:2.11.3:compile
[INFO] |  |  |  +- com.fasterxml.jackson.core:jackson-annotations:jar:2.11.3:compile
[INFO] |  |  |  \- com.fasterxml.jackson.core:jackson-core:jar:2.11.3:compile
[INFO] |  |  +- com.fasterxml.jackson.datatype:jackson-datatype-jdk8:jar:2.11.3:compile
[INFO] |  |  +- com.fasterxml.jackson.datatype:jackson-datatype-jsr310:jar:2.11.3:compile
[INFO] |  |  \- com.fasterxml.jackson.module:jackson-module-parameter-names:jar:2.11.3:compile
[INFO] |  +- org.springframework.boot:spring-boot-starter-tomcat:jar:2.4.1:compile
[INFO] |  |  +- org.apache.tomcat.embed:tomcat-embed-core:jar:9.0.41:compile
[INFO] |  |  +- org.glassfish:jakarta.el:jar:3.0.3:compile
[INFO] |  |  \- org.apache.tomcat.embed:tomcat-embed-websocket:jar:9.0.41:compile
[INFO] |  +- org.springframework:spring-web:jar:5.3.2:compile
[INFO] |  |  \- org.springframework:spring-beans:jar:5.3.2:compile
[INFO] |  \- org.springframework:spring-webmvc:jar:5.3.2:compile
[INFO] |     +- org.springframework:spring-aop:jar:5.3.2:compile
[INFO] |     +- org.springframework:spring-context:jar:5.3.2:compile
[INFO] |     \- org.springframework:spring-expression:jar:5.3.2:compile
[INFO] +- org.springframework.boot:spring-boot-starter-thymeleaf:jar:2.4.1:compile
[INFO] |  +- org.thymeleaf:thymeleaf-spring5:jar:3.0.11.RELEASE:compile
[INFO] |  |  +- org.thymeleaf:thymeleaf:jar:3.0.11.RELEASE:compile
[INFO] |  |  |  +- org.attoparser:attoparser:jar:2.0.5.RELEASE:compile

解決版本沖突的方式主要兩種:

  1. 通過上面的命令找到不需要的版本之后,在引入的依賴中,使用exclusions將其排除,比如下面這樣:
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jdbc</artifactId>
    <exclusions>
        <exclusion>
            <groupId>xxx</groupId>
            <artifactId>yyy</artifactId>
        </exclusion>
    </exclusions>
</dependency>
  1. pom.xml中強(qiáng)制指定要使用的版本,這樣這個(gè)優(yōu)先級最高,就不會引入其他版本要帶進(jìn)來的版本了。

好了,今天的分享到這里結(jié)束了,希望對你有所幫助。如果您覺得本文有用,歡迎轉(zhuǎn)發(fā)擴(kuò)散!

歡迎關(guān)注我的公眾號:程序猿DD,獲得獨(dú)家整理的免費(fèi)學(xué)習(xí)資源助力你的Java學(xué)習(xí)之路!另每周贈書不停哦~

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 一、問題描述 聽同事反饋,通過發(fā)布平臺發(fā)布了一個(gè)新版本,總共發(fā)布到了多臺機(jī)器,但是只有其中一臺報(bào)了NoSuchMe...
    jerrik閱讀 3,955評論 0 8
  • 久違的晴天,家長會。 家長大會開好到教室時(shí),離放學(xué)已經(jīng)沒多少時(shí)間了。班主任說已經(jīng)安排了三個(gè)家長分享經(jīng)驗(yàn)。 放學(xué)鈴聲...
    飄雪兒5閱讀 7,867評論 16 22
  • 今天感恩節(jié)哎,感謝一直在我身邊的親朋好友。感恩相遇!感恩不離不棄。 中午開了第一次的黨會,身份的轉(zhuǎn)變要...
    余生動聽閱讀 10,912評論 0 11
  • 可愛進(jìn)取,孤獨(dú)成精。努力飛翔,天堂翱翔。戰(zhàn)爭美好,孤獨(dú)進(jìn)取。膽大飛翔,成就輝煌。努力進(jìn)取,遙望,和諧家園??蓯塾巫?..
    趙原野閱讀 3,542評論 1 1
  • 在妖界我有個(gè)名頭叫胡百曉,無論是何事,只要找到胡百曉即可有解決的辦法。因?yàn)槭侵缓偞蠹乙杂瀭饔灲形摇皟A城百曉”,...
    貓九0110閱讀 3,728評論 7 3

友情鏈接更多精彩內(nèi)容