<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          類加載常見錯(cuò)誤總結(jié),寫得非常好!

          共 2957字,需瀏覽 6分鐘

           ·

          2021-05-05 08:50

          點(diǎn)擊關(guān)注公眾號(hào),Java干貨及時(shí)送達(dá)

          作者:fredalxin
          地址:https://fredal.xin/classloader-error

          最近在做類隔離相關(guān)的一些工作,而恰恰之前協(xié)助開發(fā)同學(xué)時(shí)也發(fā)現(xiàn)會(huì)遇到許多類加載相關(guān)的異常,并且往往比較難定位與解決。這里簡(jiǎn)單做一個(gè)小總結(jié)。

          類加載

          首先我們來捋一捋類加載的基礎(chǔ)知識(shí)。

          以上是大家比較熟悉的類加載器模型,主要包含 3 種類加載器:

          此外我們比較需要知道的幾點(diǎn):

          ClassNotFoundException

          ClassNotFoundException 表示類找不到異常,是一種 Exception,通常發(fā)生在載入階段,當(dāng)開發(fā)者主動(dòng)調(diào)用 Class.forName()、ClassLoader.loadClass()ClassLoader.findSystemClass()動(dòng)態(tài)加載指定類時(shí)候,類加載器就會(huì)去 classpath 下尋找類,如果找不到就會(huì)拋出此錯(cuò)誤。

          還有另外一種情況是當(dāng)一個(gè)類已經(jīng)被某個(gè)類加載器加載到內(nèi)存中,另外一個(gè)類加載器試圖去加載時(shí)也會(huì)發(fā)生錯(cuò)誤。

          ClassNotFoundException 是一個(gè) exception 類,同時(shí)發(fā)生在主動(dòng)執(zhí)行動(dòng)態(tài)加載時(shí),所以我們應(yīng)該去 catch 它,防止發(fā)生一些運(yùn)行時(shí)錯(cuò)誤。另外,關(guān)注公眾號(hào)Java技術(shù)棧,在后臺(tái)回復(fù):JVM46,可以獲取一份 46 頁的 JVM 高清教程,非常齊全。

          NoClassDefFoundError

          NoClassDefFoundError 是一種和 ClassNotFoundException 很像的錯(cuò)誤,只不過它是更嚴(yán)重的 error 類型。它發(fā)生在鏈接階段,表示 jvm 在編譯階段可以找到相應(yīng)的類,但在執(zhí)行過程中卻找不到相應(yīng)的類。

          一種原因是由于在編譯后運(yùn)行前類被更改或者刪除了。另外一種則是 classpath 本身被修改過了,這可以通過System.getProperty("java.classpath")來找到程序?qū)嶋H運(yùn)行的 classpath,或者通過-classpath 命令來指定正確的 classpath。

          那如果是在 ide 中開發(fā),很多時(shí)候出現(xiàn)的情況是我們可以通過 ide 編譯通過,但在實(shí)際運(yùn)行的 WEB-INF/lib 下卻是沒有的。所以排查的時(shí)候我們需要去實(shí)際的 war 包下面確定是否有類。

          NoSuchMethodError

          我們還會(huì)遇到 NoSuchMethodError 錯(cuò)誤,它表示找不到方法,但找不到方法歸根結(jié)底是找到了不正確的類。

          通常情況下是因?yàn)?jar 包沖突問題,即加載了不匹配版本的類導(dǎo)致的。例如應(yīng)用中有 A、B 兩個(gè)二方包,A 依賴 C-v1 包,而 B 依賴 C-v2 包,如果 maven 仲裁最后使用的是 C-v1 包,那么當(dāng) B 加載到 C-v2 中有而 C-v1 中沒有的方法時(shí)就會(huì)報(bào) NoSuchMethodError。

          這種情況我們首先得知道 jvm 到底加載的是什么版本,這可以使用-verbose:class來確定。Java 系列教程及實(shí)踐源碼:https://github.com/javastacks/javastack

          LinkageError

          LinkageError 相比較之前幾種錯(cuò)誤不那么常見,只有多個(gè)類加載器同時(shí)作用交互時(shí)才會(huì)出現(xiàn)。另外,關(guān)注公眾號(hào)Java技術(shù)棧,在后臺(tái)回復(fù):面試,可以獲取我整理的 JVM 系列面試題和答案,非常齊全。

          我們知道 jvm 中一個(gè)類由全限定類名與類加載器確定類實(shí)例,那么不同類加載器加載的同一個(gè)類是屬于不同類實(shí)例的,然后在內(nèi)存中如果兩者發(fā)生交互,就會(huì)出現(xiàn) LinkageError 異常。

          一般情況下,jvm 加載類都會(huì)遵循之前所述的雙親委派原則,不太可能出現(xiàn)一個(gè)類有不同類加載器加載的情況。但在諸如 tomcat 之類的 javaEE 環(huán)境中,常常出這種狀況,這是由于 tomcat 上的 web 應(yīng)用類加載機(jī)制稍有不同,每個(gè)資源模塊(比如一個(gè) war 包)都優(yōu)先使用自身的資源,突破了雙親委派模型:

          當(dāng) appClassLoader 加載類時(shí)候,會(huì)首先在自己的本地資源庫中查找類,其次才會(huì)走雙親委派模型。那么如果一個(gè)類 A 由 AppClassLoaderx 加載,但其超類在 AppClassLoader 中沒有,只有委托 CommonClassLoader 才能找到,當(dāng)類 A 與其超類進(jìn)行交互時(shí)就會(huì)報(bào)錯(cuò)了。

          還有一種比較常見的情況是進(jìn)行自定義類加載器開發(fā)時(shí)遇到。比如開發(fā)類隔離容器時(shí),期望將某些中間件都由與應(yīng)用不同的獨(dú)立類加載器加載,但這時(shí)候如果中間件依賴 spring context,而應(yīng)用本身也依賴 spring context,那么 作為 spring bean 交互時(shí)候就會(huì)妥妥報(bào) LinkageError 了。Spring Boot 系列教程推薦:https://github.com/javastacks/spring-boot-best-practice

          解決這個(gè)問題的辦法包括 2 種,即控制不同類加載器加載的類不進(jìn)行交互,或者都交于一個(gè)共同的父加載器進(jìn)行加載。

          Some Tips

          總結(jié)一下以上幾種錯(cuò)誤。ClassNotFoundException 以及 NoClassDefFoundError 都是由于加載不到類導(dǎo)致的,而 NoSuchMethodError 是因?yàn)榧虞d了不正確的類,LinkageError 則是由于同一個(gè)類被多個(gè)類加載器加載所導(dǎo)致的。

          以上這些問題都可以使用arthas進(jìn)行排查。例如使用 sc 命令來查看 JVM 已加載的類信息,包括從哪個(gè) jar 包讀取,由哪個(gè)類加載器加載。使用 jad 命令來查看 jvm 中反編譯的代碼,可以定位到底到底有沒有所需 method。以及使用 classloader 命令,來查看當(dāng)前所有 classloader 的信息,包括加載的 urls,是否能加載到指定的類或者 resources 等。






          關(guān)注Java技術(shù)棧看更多干貨



          獲取 Spring Boot 實(shí)戰(zhàn)筆記!
          瀏覽 22
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  www.超| 久热国产视频 | 日本在线中文 | 欧洲级毛片内射 | 国产免费黄色视频网站 |