ExceptionInInitializerError-靜態(tài)代碼塊的細(xì)節(jié)

ExceptionInInitializerError-靜態(tài)代碼塊的細(xì)節(jié)

背景描述

某日調(diào)試的過程中發(fā)現(xiàn)一個(gè)非常奇怪的錯(cuò)誤,在IDEA中debug過程中我沒有辦法獲取一個(gè)已經(jīng)申請(qǐng)好的靜態(tài)變量,接口也每每執(zhí)行到此處就會(huì)跳錯(cuò)。那么按思路來說,縮小問題范圍,集中精力去發(fā)現(xiàn)這個(gè)問題根源。于是編寫單元測(cè)試對(duì)這一小截代碼進(jìn)行測(cè)試。出處部分主要來自下面這一段

    public static Map<String, String> urlMapping = new ConcurrentHashMap<>();

    static {
        ConfigUtil.init();
        urlMapping.put("xxx", PARTICIPLESURL);
        urlMapping.put("yyy", INTENTURL);
        urlMapping.put("zzz", SORTURL);
    }

甚至報(bào)錯(cuò)了NoClassDefFoundError的錯(cuò)誤。一般來說,NoClassDefFound這個(gè)錯(cuò)誤常發(fā)生于依賴沖突的場(chǎng)景,但現(xiàn)在在調(diào)用自己的類出現(xiàn)這個(gè)問題就非常不可思議。日志中的錯(cuò)誤棧也比較冗長(zhǎng),影響了一開始捕獲關(guān)鍵信息的難度。

問題現(xiàn)象

觀察日志棧中可以發(fā)現(xiàn)有一個(gè)區(qū)分度比較明顯的錯(cuò)誤

java.lang.ExceptionInInitializerError

這個(gè)就是答案的解。這個(gè)錯(cuò)誤的意思其實(shí)是在靜態(tài)代碼塊中如果加載出錯(cuò)的會(huì)統(tǒng)一跳出這個(gè)Error。因?yàn)槭荅rror還沒辦法被普通的try-catch捕獲。
那之前的那個(gè)說的那個(gè)錯(cuò)誤

noclassdeffounderror: could not initialize class

又是怎么回事呢?我們知道jvm在需要加載類時(shí)會(huì)先加載類中的靜態(tài)代碼塊和靜態(tài)變量等。靜態(tài)代碼塊出現(xiàn)了沒有被捕獲的錯(cuò)誤,代碼塊崩潰,導(dǎo)致整個(gè)類加載失敗,jvm找不到這個(gè)類,順理成章的引出了上面這個(gè)錯(cuò)誤。這個(gè)錯(cuò)誤很容易往依賴沖突的方向去想,而偏離了問題的本質(zhì)。
那么代碼的問題又處在哪里呢?主要是ConcurrentHashMap的k和v是不允許為null空值的,而在當(dāng)時(shí)環(huán)境下被賦予了空值報(bào)錯(cuò)沒有接住導(dǎo)致的這個(gè)問題。ConcurrentHashMap不允許kv空值和本身需要做線程同步有關(guān),而HashMap就沒有這個(gè)問題,在非多線程環(huán)境下,即一塊內(nèi)存只會(huì)被一個(gè)線程訪問時(shí),還是使用HashMap就可以了。效率上也比ConcurrentHashMap快,因?yàn)镃oncurrentHashMap內(nèi)部還有為線程同步上鎖的問題存在。

解決方式

沒什么特別值得書寫的,最重要的還是知道了這個(gè)報(bào)錯(cuò)的原因,解決方式無非根據(jù)場(chǎng)景處理了空值現(xiàn)象。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,048評(píng)論 25 709
  • Java SE 基礎(chǔ): 封裝、繼承、多態(tài) 封裝: 概念:就是把對(duì)象的屬性和操作(或服務(wù))結(jié)合為一個(gè)獨(dú)立的整體,并盡...
    Jayden_Cao閱讀 2,247評(píng)論 0 8
  • 01 閑來無事,我就會(huì)在各種聊天群里看他們說話,碰到能聊也會(huì)跳出去插上一兩句話。 前天晚上十點(diǎn)多了,有一位姑娘在群...
    靈林玖玖閱讀 1,028評(píng)論 7 4
  • 人生很少有捷徑讓你一飛沖天 大多數(shù)路都是顛簸的 人生越不好走的路,就越想有捷徑早日擺脫 ...
    摩西44閱讀 121評(píng)論 0 0
  • Command line instructions Git global setup 初始化賬號(hào) Create...
    只因?yàn)槌媚贻p閱讀 259評(píng)論 0 0

友情鏈接更多精彩內(nèi)容