JAR衝突問題的解決以及執行狀態下如何檢視載入的類
阿新 • • 發佈:2021-01-18
今天碰到群裡小夥伴問,線上程式好像有多個不同版本的Netty包,怎麼去看到底載入了哪一個?
在說如何看之前,先來說說,當你開始意識到專案裡有多個不同版本的Jar包,都是因為遇到了這幾個異常:
1. `java.lang.NoSuchMethodException`:自己程式碼中呼叫了某個方法,因為載入了其他版本的jar,這個版本正好沒這個方法。
2. `java.lang.NoClassDefFoundError`:編譯時候是好的,但是執行的時候,因為載入的jar版本問題,沒有這個類。
3. `java.lang.ClassNotFoundException`:在動態載入某個Class的時候,因為要載入的jar不是正確的版本,而導致找不到這個類。
當你在本地執行ok,但到伺服器上發現出現這些錯誤的時候,就要意識到很可能是jar衝突了(有相同依賴存在多個版本)。這個問題往往也會有這樣的表現:多例項部署的時候,有的例項是好的,有的例項則不行。
## 檢視載入的類和方法
根據之前分析的異常種類,我們可以去執行中的現場確認當前載入的問題。
這裡我們可以使用阿里開源的Arthas工具,如果第一次用,那麼按下面操作先安裝再執行:
```bash
curl -O https://arthas.aliyun.com/arthas-boot.jar
java -jar arthas-boot.jar
```
執行好之後,會打印出當前執行著的java應用,比如:
```
[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應用,比如這裡選擇:1,進入到chapter4-3-0.0.1-SNAPSHOT.jar中去。
下面介紹兩個重要命令:
第一個:`sc`命令,我們確認一下可能衝突的jar包下面,是否有對應的class。有些不同版本包下class就不一樣,馬上就可以分辨出來。
比如,通過下面的命令,我們檢視一下`com.didispace`包下有什麼類:
```bash
[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.
```
第二個:`sm`命令,檢視具體某個類有哪些方法。有的版本差異就是去掉了某個方法,這個時候我們就可以通過這個命令來檢視。
比如,通過下面的命令,我們檢視一下`com.didispace.chapter43.UploadController`類下有些什麼方法:
```bash
[arthas@40611]$ sm com.didispace.chapter43.UploadController
com.didispace.chapter43.UploadCon