成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

JVM 對(duì) NoClassDefFoundError 的“緩存”

dayday_up / 431人閱讀

摘要:于是懷疑是不是對(duì)一個(gè)類的做了緩存,在第一次加載這個(gè)類出現(xiàn)以后,后續(xù)再嘗試加載就直接拋出。上述類的的作用是是一個(gè)空的類,里面有一個(gè)的靜態(tài)成員。

問題

今天在排查一個(gè)線上的問題,線上的一個(gè)應(yīng)用在初始化一個(gè)類的靜態(tài)字段的時(shí)候出現(xiàn)了 NoClassDefFoundError,并且在導(dǎo)致 NoClassDefFoundError 出現(xiàn)的根本原因消失后,后續(xù)再次嘗試初始化這個(gè)類的時(shí)候,持續(xù)出現(xiàn)了 NoClassDefFoundError。

于是懷疑 JVM 是不是對(duì)一個(gè)類的 NoClassDefFoundError 做了緩存,在第一次加載這個(gè)類出現(xiàn) NoClassDefFoundError 以后,后續(xù)再嘗試加載就直接拋出 NoClassDefFoundError。

實(shí)驗(yàn)

為了證實(shí)自己的猜想,嘗試設(shè)計(jì)了一個(gè)簡單的實(shí)驗(yàn),一個(gè)涉及三個(gè)類

public class Test1 {
    static Test2 test2 = new Test2();
}
public class Test2 {
}
public class Test {
    public static void main(String... args) throws Exception {
        while(true) {
            System.out.println("================================");
            try {
                new Test1(); // 嘗試實(shí)例化 Test1,觸發(fā) NoClassDefFoundError
            } catch (Throwable e) {
                e.printStackTrace();

                try {
                    Test.class.getClassLoader().loadClass("Test2"); // 嘗試加載 Test2,用于證實(shí)當(dāng)將 
                                                                    // Test2.class 拷貝到 ClassPath 下的時(shí)候,
                                                                    // Test2 就可以加載到了。
                } catch (Throwable ex) {
                    ex.printStackTrace();
                }
            }
            Thread.sleep(3000);
        }
    }
}

上述類的的作用是:Test2 是一個(gè)空的類,Test1 里面有一個(gè) Test2 的靜態(tài)成員。Test 是程序的主入口,在一個(gè)無限循環(huán)內(nèi)部,不斷地嘗試去實(shí)例化 Test1,并且在加載 Test1 出現(xiàn)異常的時(shí)候,嘗試加載一下 Test2。

實(shí)驗(yàn)的步驟是:

編譯以上類,運(yùn)行 javac Test.java

將生成出的 Test2.class 重命名成 Test2.class.bak

運(yùn)行 java Test,這個(gè)時(shí)候程序去加載 Test1 的時(shí)候,就會(huì)出現(xiàn) NoClassDefFoundError,并且在嘗試加載 Test2 的時(shí)候,會(huì)出現(xiàn) ClassNotFoundException。

將第二步重命名的 Test2.class.bak 該回成 Test2.class,這個(gè)時(shí)候程序去加載 Test1 的時(shí)候,就會(huì)出現(xiàn) NoClassDefFoundError,在加載 Test2 的時(shí)候,不會(huì)出現(xiàn) ClassNotFoundException。

實(shí)驗(yàn)的第二步的目的是為了程序在加載 Test1 的時(shí)候因?yàn)檎也坏?Test2 出現(xiàn) NoClassDefFoundError,第四步是為了和第二步做對(duì)照,說明在后續(xù)程序可以加載到 Test2 的時(shí)候,在實(shí)例化 Test1 的時(shí)候,依舊出現(xiàn) NoClassDefFoundError

在我的機(jī)器上,按照上面的方式去操作,結(jié)果如下:

結(jié)果正如預(yù)期,即使在后面 Test2 在 ClassPath 下的時(shí)候,NoClassDefFoundError 依舊出現(xiàn),所以 JVM 里面肯定有地方對(duì) NoClassDefFoundError 做了緩存。

JVM 里面的實(shí)現(xiàn)

帶著這個(gè)疑問,請(qǐng)教了部門里面的 JVM 專家,這個(gè)猜測得到了證實(shí),并且他給出了 JVM 內(nèi)部具體處理這段邏輯的代碼,處理的代碼在 JDK 的 instanceKlass.cpp 這個(gè)文件里面:

bool instanceKlass::link_class_impl(
     instanceKlassHandle this_oop, bool throw_verifyerror, TRAPS) {
   // check for error state
   if (this_oop->is_in_error_state()) {
     ResourceMark rm(THREAD);
     THROW_MSG_(vmSymbols::java_lang_NoClassDefFoundError(),
                this_oop->external_name(), false);
   }
   // return if already verified
   if (this_oop->is_linked()) {
     return true;
   }

并且在 instanceClass.hpp 這個(gè)文件中,定義了類的 _init_state,其中,is_in_error_state 這個(gè)方法的定義如下:

bool is_in_error_state() const           { return _init_state == initialization_error; }

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/64242.html

相關(guān)文章

  • java基礎(chǔ)小記

    摘要:看到的只是,而由泛型附加的類型信息對(duì)來說是不可見的。然后再加載執(zhí)行類的靜態(tài)變量以及靜態(tài)語句塊。接口中基本數(shù)據(jù)類型為而抽類象不是的。本地方法接口主要是調(diào)用或?qū)崿F(xiàn)的本地方法及返回結(jié)果。用戶自定義類加載器,在程序運(yùn)行期間,通過的子類動(dòng)態(tài)加載。 編譯機(jī)制  編譯主要是把?.Java文件轉(zhuǎn)換為 .class 文件。其中轉(zhuǎn)換后的 .class 文件就包含了元數(shù)據(jù),方法信息等一些信息。比如說元數(shù)據(jù)就...

    ruicbAndroid 評(píng)論0 收藏0
  • 崩潰bug日志總結(jié)2

    摘要:出現(xiàn)錯(cuò)誤引發(fā)崩潰日志的流程分析這個(gè)錯(cuò)誤是應(yīng)用的方法總數(shù)限制造成的。 目錄介紹 1.1 java.lang.ClassNotFoundException類找不到異常 1.2 java.util.concurrent.TimeoutException連接超時(shí)崩潰 1.3 java.lang.NumberFormatException格式轉(zhuǎn)化錯(cuò)誤 1.4 java.lang.Illegal...

    sutaking 評(píng)論0 收藏0
  • 夯實(shí)基礎(chǔ)系列一:Java 基礎(chǔ)總結(jié)

    摘要:可實(shí)現(xiàn)單例模式代碼塊初始化靜態(tài)變量,只被執(zhí)行一次內(nèi)部類不能與外部類重名,只能訪問外部類靜態(tài)數(shù)據(jù)包括私有多分支選擇整型或字符類型變量或整數(shù)表達(dá)式開始支持。 前言 大學(xué)期間接觸 Java 的時(shí)間也不短了,不論學(xué)習(xí)還是實(shí)習(xí),都讓我發(fā)覺基礎(chǔ)的重要性?;ヂ?lián)網(wǎng)發(fā)展太快了,各種框架各種技術(shù)更新迭代的速度非常快,可能你剛好掌握了一門技術(shù)的應(yīng)用,它卻已經(jīng)走在淘汰的邊緣了。 而學(xué)習(xí)新技術(shù)總要付出一定的時(shí)間...

    greatwhole 評(píng)論0 收藏0
  • JVM中dump出動(dòng)態(tài)代理生成class

    摘要:方案一設(shè)置運(yùn)行環(huán)境變量運(yùn)行后會(huì)把文件生成在目錄下動(dòng)態(tài)代理時(shí)生成文件缺點(diǎn)是只適用于動(dòng)態(tài)代理方案二使用可以出中所有已加載的。 由于動(dòng)態(tài)代理生成的class是直接以二進(jìn)制的方式加載進(jìn)內(nèi)存中的,并沒有對(duì)應(yīng)的.class文件生成,所以如果想通過反編譯工具查看動(dòng)態(tài)代理生成的代碼需要通過特殊的手段來處理。 方案一 設(shè)置運(yùn)行環(huán)境變量,運(yùn)行后會(huì)把class文件生成在classpath目錄下 //動(dòng)態(tài)代理...

    sherlock221 評(píng)論0 收藏0
  • Android 使用fastjson找不到fastjson包問題解決方法

    摘要:但是將導(dǎo)入工程后,在使用時(shí)會(huì)出現(xiàn)等錯(cuò)誤消息。初步認(rèn)為是與自帶的沖突。再運(yùn)行工程,這個(gè)錯(cuò)誤不再出現(xiàn)了,奇跡般的沒問題了。我的理解是這樣,不知道對(duì)不對(duì),歡迎大俠指正。工程中下默認(rèn)的是,而則應(yīng)該是。所以按照該文的解決方法,更改就好了。 JSON解析庫有很多,諸如Jackson,Json-lib,org.json,Gson和fastjson等,但是fastjson以其解析速度最快而脫穎而出。詳...

    hiYoHoo 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<