總結一次類型轉換異常的解決

      先說下本人是1年外包狗,正在學習的路上摸爬滾打。週五在和其餘系統進行聯調的時候,人家反饋說一調用個人服務流程就異常中斷了。我這裏的應用日誌一直開着,也沒看見請求進來,忽然靈光一閃我怎麼忘記了服務器日誌,打開一看,果真報錯了,錯誤描述 :java.lang.ClassCastException。再具體一看報錯的地方,這是好幾年前就寫好且在生產上運行着的組件啊,爲何忽然就出現一個類型轉換錯誤呢?

       要解決這個問題,首先說下我這的系統架構,以下圖。html


調用流程就是請求進來服務器到應用2,經過一個寫好的組件C將請求發送到子系統進行處理。有人確定會問應用1是幹嗎的,它僅僅只是用來啓動子系統的,沒有其餘卵用,子系統經過應用1來掛載到服務器上。應用2經過JNDI來調用子系統中的服務,此時就要經過java

CProxy c=(CProxy)ctx.lookup(jndiname)來進行強轉了。CProxy就是組件C中的一個類,主要用來進行數據交換的。而後就是這個地方,出現了java.lang.ClassCastException。說實話,看到這個錯,我很茫然,啥玩意兒,生產上不是跑着的?你如今告訴我測試環境出了問題。頓時一陣涼涼,我不會把哪一個地方給搞錯了吧,擦。因而我趕忙把測試版本回退到了一個月前,調用老的服務,仍是報錯了,此時的我是懵逼的,弱小無助。服務器

     這塊工做內容除了我還有一位公司的多年老開發也很熟,因而我就去問他了,他負責這塊業務不少年,也有一些經驗。然而結果讓人失望,他也不會,他給的那些排查方案我一看就知道方向不對,算了,這個坑看來仍是得本身填。因而乎,我就在網上開始了個人尋找答案之旅。因爲這塊技術太過老舊,資源也少,週五找了一夜也沒什麼收穫,一開始就以爲多是服務器升級打補丁形成的,由於生產在運行給了我一個錯覺。一晚上沒有什麼進展,週六我又去公司進行測試排查問題出現的緣由。首先檢查了服務器文件,檢查了子系統文件,發現除了補丁包之外最後修改時間都是3年前的了。強轉異常出如今應用2中,JNDI服務提供者是子系統,因而我去拿着相同的代碼去子系統測試,沒有報錯。那問題確定就是在應用2中了,但是應用2也只是用來與其餘系統進行通信用,幾年沒動過了,陷入僵局。週日繼續加班,這裏說下類型轉換異常在什麼狀況下會發生,第一:父類引用指向的對象的類型不是子類的時候將產生java.lang.ClassCastException異常,這個你們應該都懂;第二:類型是它的類型,可是爲何也會報錯,由於ClassLoader不一致,也會致使java.lang.ClassCastException異常。在JVM中,類只會被加載一次,類的雙親委派模型中類的加載過程這裏就不細講了,反正大概就行檢查一下有沒有被加載,沒有被加載就給委派父類加載器去加載,父類加載器加載不了纔會給子類加載器加載, 貼個找的圖架構

                                    

我在應用2中將CProxylookup()所產生的對象的類加載器給打印出來了,發現他們是不同的,CProxy用的是SystemClassloader,而lookup()產生的竟然是一個自定義的類加載器。另外我在子系統中也把他們的classloader打印了出來,都是用自定義類加載器加載的,而這個自定義類加載器就是子系統的。報錯的緣由是已經找到了,可是我又開始疑惑了,組件C是寫在服務器的啓動腳本中定義的CLASSPATH環境變量中的,若是遵循雙親委派模型的規則,都應該是由SystemClassloader加載的纔對。看來得翻子系統的源代碼了,因而乎又去把子系統的啓動類反編譯了來看下,發現它實現了本身的類加載器去加載指定路徑的全部jar,重點來了,它違背了雙親委派模型的原則,再也不是先交由父加載器去加載,而是反轉了過來,優先使用本身的自定義類加載器去加載指定路徑的jar,若是加載不到,就會委派父加載器去加載。因此報錯的現象就能夠解釋了,爲何同一個類卻產生了不一樣的類加載器。那麼如何解決呢,也很簡單,只須要把組件C從子系統的加載路徑下移除,從新找個位置放就能夠了,再改下腳本中CLASSPATH加載此組件的路徑。運維

      其實我如今也不清楚生產這幾年是怎麼過來的,按道理來說應該會報錯,公司領導說老交易其實已經沒有交易量了,可是至少當時投產部署,測試環境測試過吧,難道沒有出現問題?我如今也很疑惑,以致於如今雖然沒有報錯了,但也懷疑本身是否是還有什麼地方沒有關注到。學習

最後再貼幾篇我以爲受益的classloader相關的文章。測試

1.查看JVM加載的類及類加載器的方法3d

www.cnblogs.com/z00377750/p…
日誌

2.JNDI 詳解code

wenku.baidu.com/view/81e687…

3.深刻淺出ClassLoader

ifeve.com/classloader…

4.ClassLoader

www.cnblogs.com/549294286/p…

--- 2019.8.31  ps:

上線後的感悟。

做爲一個小白,其實在工做中不少比較重要的任務上級都不會派給你,須要本身去不斷深挖學習技術或是業務相關的ererything,這樣纔會在關鍵時刻凸顯本身的做用。這個問題解決後我特意去讓運維幫我覈查了生產相關的配置,發現是正確的。從這件事也反映出工做中版本管理、環境管理的重要性,不然就會出現不少奇奇怪怪的問題,就像此次上線同樣,測試環境沒問題,生產上報錯,排查到後半夜發現是測試與生產jdk不一致致使,生產多了一個jar,致使了衝突。

相關文章
相關標籤/搜索