玩大發了,Tomcat 8.5 升級有坑…

最近某全系統做了環境升級:

  • Tomcat 8.5.x
  • JDK 1.8.x

有個系統升級後出現沒有這個方法異常:

threw exception; nested exception is java.lang.NoSuchMethodError: 
...
...

上線後系統起不來,這下玩大了。。。

咋一看應該是 jar 包衝突了,經過排查,果然是 jar 包衝突了,類路徑下存在了幾個不同版本類似的 jar 包,是由另外一個依賴引入進來的 compile 依賴,然後排除衝突的依賴就解決了。

那麼問題來了,既然 jar 包衝突,相同的環境,爲什麼在開發環境、測試環境、預上線環境都沒有出現問題?

經過查證,那是因爲 Tomcat 8 之後的 jar 包加載方式變了,8 之前是按照字母順序加載的,而 8 之後就變了,Tomcat 使用的是 File.listFiles() 方法來獲取目前下的 jar 包,加載的順序就和文件系統返回的順序有關,就不一定是按字母排序了。

java.io.File#listFiles() 源碼註釋:

這個方法是獲取目前下的所有文件,它不能保證按指定的順序返回結果,特別是,不能保證按字母順序返回。爲什麼本地環境可以,可能是剛好是按字母排序的了。

那麼,這個問題的解決辦法可以是:

1)如果是衝突問題,排除衝突依賴解決 jar 包衝突或者降級到 tomcat 7 就行了,又或者是寫個腳本檢查一下包名是否有重複的包;我們剛好是有兩個 jar 包衝突了,解決衝突就正常了;

2)如果是業務問題,我們都知道 JVM 雙親委派機制,同一個類是不能重複加載的,如果業務確實需要加載多個版本的依賴,那就需要實現自己的自定義類加載器分別去加載對應的 jar 包;

關於類加載器、雙親委派機制都可以在Java技術棧公衆號往期文章找到相對應的解答。

關注公衆號Java技術棧回覆"面試"獲取我整理的2020最全面試題及答案。

推薦去我的博客閱讀更多:

1.Java JVM、集合、多線程、新特性系列教程

2.Spring MVC、Spring Boot、Spring Cloud 系列教程

3.Maven、Git、Eclipse、Intellij IDEA 系列工具教程

4.Java、後端、架構、阿里巴巴等大廠最新面試題

覺得不錯,別忘了點贊+轉發哦!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章