日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

不可逆的类初始化过程

發(fā)布時間:2025/3/21 19 豆豆
生活随笔 收集整理的這篇文章主要介紹了 不可逆的类初始化过程 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

類的加載過程說復雜很復雜,說簡單也簡單,說復雜是因為細節(jié)很多,比如說今天要說的這個,可能很多人都不了解;說簡單,大致都知道類加載有這么幾個階段,loaded->linked->initialized,為了讓大家能更輕松地知道我今天說的這個話題,我不詳細說類加載的整個過程,改天有時間有精力了我將整個類加載的過程和大家好好說說(PS:我對類加載過程慢慢清晰起來得益于當初在支付寶做cloudengine容器開發(fā)的時候,當時引入了標準的osgi,解決類加載的問題幾乎是每天的家常便飯,相信大家如果還在使用OSGI,那估計能體會我當時的那種痛,哈哈)。

本文我想說的是最后一個階段,類的初始化,但是也不細說其中的過程,只圍繞我們今天要說的展開。

我們定義一個類的時候,可能有靜態(tài)變量,可能有靜態(tài)代碼塊,這些邏輯編譯之后會封裝到一個叫做clinit的方法里,比如下面的代碼:

class BadClass{private static int a=100;static{System.out.println("before init");int b=3/0;System.out.println("after init");}public static void doSomething(){System.out.println("do somthing");} }

編譯之后我們通過javap -verbose BadClass可以看到如下字節(jié)碼:

{BadClass();flags:Code:stack=1, locals=1, args_size=10: aload_01: invokespecial #1 ? ? ? ? ? ? ? ? ?// Method java/lang/Object."<init>":()V4: returnLineNumberTable:line 1: 0public static void doSomething();flags: ACC_PUBLIC, ACC_STATICCode:stack=2, locals=0, args_size=00: getstatic ? ? #2 ? ? ? ? ? ? ? ? ?// Field java/lang/System.out:Ljava/io/PrintStream;3: ldc ? ? ? ? ? #3 ? ? ? ? ? ? ? ? ?// String do somthing5: invokevirtual #4 ? ? ? ? ? ? ? ? ?// Method java/io/PrintStream.println:(Ljava/lang/String;)V8: returnLineNumberTable:line 10: 0line 11: 8static {};flags: ACC_STATICCode:stack=2, locals=1, args_size=00: bipush ? ? ? ?1002: putstatic ? ? #5 ? ? ? ? ? ? ? ? ?// Field a:I5: getstatic ? ? #2 ? ? ? ? ? ? ? ? ?// Field java/lang/System.out:Ljava/io/PrintStream;8: ldc ? ? ? ? ? #6 ? ? ? ? ? ? ? ? ?// String before init10: invokevirtual #4 ? ? ? ? ? ? ? ? ?// Method java/io/PrintStream.println:(Ljava/lang/String;)V13: iconst_314: iconst_015: idiv16: istore_017: getstatic ? ? #2 ? ? ? ? ? ? ? ? ?// Field java/lang/System.out:Ljava/io/PrintStream;20: ldc ? ? ? ? ? #7 ? ? ? ? ? ? ? ? ?// String after init22: invokevirtual #4 ? ? ? ? ? ? ? ? ?// Method java/io/PrintStream.println:(Ljava/lang/String;)V25: returnLineNumberTable:line 2: 0line 4: 5line 5: 13line 6: 17line 7: 25 }

我們看到最后那個方法static{},其實就是我上面說的clinit方法,我們看到靜態(tài)字段的初始化和靜態(tài)代碼庫都封裝在這個方法里。

假如我們通過如下代碼來測試上面的類:

public static void main(String args[]){try{BadClass.doSomething();}catch (Throwable e){e.printStackTrace();}BadClass.doSomething();}

大家覺得輸出會是什么?是會打印多次before init嗎?其實不然,輸出結果如下:

before init java.lang.ExceptionInInitializerErrorat ObjectTest.main(ObjectTest.java:7)at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)at java.lang.reflect.Method.invoke(Method.java:606)at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134) Caused by: java.lang.ArithmeticException: / by zeroat BadClass.<clinit>(ObjectTest.java:25)... 6 more Exception in thread "main" java.lang.NoClassDefFoundError: Could not initialize class BadClassat ObjectTest.main(ObjectTest.java:12)at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)at java.lang.reflect.Method.invoke(Method.java:606)at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)

也就是說其實是只輸出了一次before init,這是為什么呢?

clinit方法在我們第一次主動使用這個類的時候會觸發(fā)執(zhí)行,比如我們訪問這個類的靜態(tài)方法或者靜態(tài)字段就會觸發(fā)執(zhí)行clinit,但是這個過程是不可逆的,也就是說當我們執(zhí)行一遍之后再也不會執(zhí)行了,如果在執(zhí)行這個方法過程中出現(xiàn)了異常沒有被捕獲,那這個類將永遠不可用,雖然我們上面執(zhí)行BadClass.doSomething()的時候catch住了異常,但是當代碼跑到這里的時候,在jvm里已經(jīng)將這個類打上標記了,說這個類初始化失敗了,下次再初始化的時候就會直接返回并拋出類似的異常java.lang.NoClassDefFoundError: Could not initialize class BadClass,而不去再次執(zhí)行初始化的邏輯,具體可以看下jvm里對類的狀態(tài)定義:

enum ClassState {unparsable_by_gc = 0, ? ? ? ? ? ? ? // object is not yet parsable by gc. Value of _init_state at object allocation.allocated, ? ? ? ? ? ? ? ? ? ? ? ? ?// allocated (but not yet linked)loaded, ? ? ? ? ? ? ? ? ? ? ? ? ? ? // loaded and inserted in class hierarchy (but not linked yet)linked, ? ? ? ? ? ? ? ? ? ? ? ? ? ? // successfully linked/verified (but not initialized yet)being_initialized, ? ? ? ? ? ? ? ? ?// currently running class initializerfully_initialized, ? ? ? ? ? ? ? ? ?// initialized (successfull final state)initialization_error ? ? ? ? ? ? ? ?// error happened during initialization};

如果clinit執(zhí)行失敗了,拋了一個未被捕獲的異常,那將這個類的狀態(tài)設置為initialization_error,并且無法再恢復,因為jvm會認為你這次初始化失敗了,下次肯定也是失敗的,為了防止不斷拋這種異常,所以做了一個緩存處理,不是每次都再去執(zhí)行clinit,因此大家要特別注意,類的初始化過程可千萬不能出錯,出錯就可能只能重啟了哦。

總結

以上是生活随笔為你收集整理的不可逆的类初始化过程的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 国产高潮流白浆喷水视频 | 男人的天堂av网站 | 国产在线观看免费播放 | 清清草在线视频 | 少妇被又大又粗又爽毛片久久黑人 | 亚洲精品粉嫩小泬 | 夜夜操天天干 | 久久成人午夜 | 免费a网 | 狠狠干网址 | 亚洲福利小视频 | 色图视频 | 国产极品91 | 精品成人无码久久久久久 | 涩涩涩999| 91国内精品久久久 | 亚洲免费成人在线 | 久久福利精品 | 国产一区二区三区在线看 | 日韩在线播放一区二区 | 成年女人色毛片 | 国产精品久久久久久久久久久久 | 中文字幕一区二区三区四区视频 | 深夜啪啪 | 国产精品-色哟哟 | 四虎精品成人免费网站 | 欧美一级黄色片网站 | 天天撸夜夜操 | 欧美福利第一页 | 日本熟妇一区二区 | 日韩免费电影一区 | 成人手机在线视频 | 超碰2022 | 亚洲久久在线观看 | 蜜臀av免费一区二区三区水牛 | 欧美视频一区 | 亚洲国产毛片aaaaa无费看 | 搞中出| 影音先锋在线视频 | 六月激情综合 | 国产伦精品一区二区三区88av | 九七电影院97理论片 | 欧美色图3p | 国产又粗又猛又黄又爽视频 | 成人免费在线观看网站 | 国产视频网 | 午夜影院在线播放 | 又骚又黄的视频 | 亚洲av成人无码久久精品 | 成人免费淫片aa视频免费 | 自拍中文字幕 | 日韩一级黄色录像 | 在线免费毛片 | 亚洲在线一区二区 | 男女免费毛片 | 中文字幕国产综合 | 成人精品视频99在线观看免费 | 欧美福利在线视频 | 欧美日韩在线免费看 | 爽爽av| 精品在线视频免费观看 | 色多多黄色 | 人妻少妇精品一区二区 | 91视频入口 | 亚洲影院在线 | 一级黄色片在线免费观看 | 欧美精品极品 | 五月天色网站 | 青青青草视频在线观看 | 一区二区三区视频在线播放 | 成人网在线看 | h片大全| 久久久久一区二区三区 | 日韩爱爱片| 亚洲视频网 | 欧美一区二区三区四区视频 | 国产天堂在线观看 | 亚洲专区一区二区三区 | 26uuu国产 | wwww欧美| 在线小视频 | 女人的洗澡毛片毛多 | 一区二区三区四区在线观看视频 | 欧美人与性动交a欧美精品 日韩免费高清视频 | 国产丰满美女做爰 | 国产午夜福利精品 | 理论片中文字幕 | 人妻丰满熟妇岳av无码区hd | 国产区精品区 | av在线免费观看不卡 | 国产精品久久久久久久妇 | 日韩国产一级 | 99久久久无码国产精品 | 国产福利不卡视频 | 91视频最新 | 国产精品无码专区av在线播放 | 香蕉视频在线观看免费 | 波多野结衣视频免费观看 | 国产chinesehd精品露脸 |