1. 程式人生 > >JAR衝突問題的解決以及執行狀態下如何檢視載入的類

JAR衝突問題的解決以及執行狀態下如何檢視載入的類

今天碰到群裡小夥伴問,線上程式好像有多個不同版本的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