最近某全系統做了環境升級:
- 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、后端、架構、阿里巴巴等大廠最新面試題
覺得不錯,別忘了點贊+轉發哦!
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/157900.html
標籤:Java
下一篇:springcloud vue.js 微服務分布式 flowable 作業流 前后分離 集成代碼生成器 shiro權限
