摘要:前置知識類的生命周期場景設計和推測情況在類中的初始化中實例化在類的初始化中實例化類設計類靜態(tài)變量靜態(tài)變量之后在靜態(tài)初始化塊里賦值為實例變量之后再初始化塊中賦值為構造函數(shù)類靜態(tài)變量靜態(tài)變量之后在靜態(tài)初始化塊里賦值為實例變量之后再初始化塊中賦值
前置知識: 類的生命周期
場景設計和推測
情況:
在類A中的初始化中實例化B
在類B的初始化中實例化A
類設計
A類:
靜態(tài)變量a=new B();靜態(tài)變量a1=1(之后在靜態(tài)初始化塊里賦值為2);
實例變量a2=11(之后再初始化塊中賦值為12);
構造函數(shù);
B類:
靜態(tài)變量b=new A();靜態(tài)變量b1=3(之后在靜態(tài)初始化塊里賦值為4);
實例變量b2=21(之后再初始化塊中賦值為22);
構造函數(shù);
猜想執(zhí)行結果: 由于類初始化之后類實例化,所以A類初始化需要B實例化,B實例化又需要A初始化,造成循環(huán)依賴,最終結果為死鎖
打點位置:
類加載結束點(text: Loaded Main2 from file)
類初始化開始點/結束點(text: Class A2 init)
實例初始化開始點/結束點(text: Instance A2 init)
構造函數(shù)結束點(text: Instance A2 new)
場景代碼class A2 { static { System.out.println("Class A2 init start"); } static B2 a = new B2(); static int a1 = 1; { System.out.println("Instance A2 init start. a=" + a + " a1=" + a1 + " a.b2=" + (a == null ? "NPE" : a.b2) + " b=" + B2.b + " b1=" + B2.b1 + " b.a2=" + (B2.b == null ? "NPE" : B2.b.a2)); } public int a2 = 11; static { a1 = 2; System.out.println("Class A2 init end. a=" + a + " a1=" + a1 + " a.b2=" + (a == null ? "NPE" : a.b2) + " b=" + B2.b + " b1=" + B2.b1 + " b.a2=" + (B2.b == null ? "NPE" : B2.b.a2)); } { a2 = 12; System.out.println("Instance A2 init end. a=" + a + " a1=" + a1 + " a.b2=" + (a == null ? "NPE" : a.b2) + " b=" + B2.b + " b1=" + B2.b1 + " b.a2=" + (B2.b == null ? "NPE" : B2.b.a2)); } public A2() { System.out.println("Instance A2 new. a=" + a + " a1=" + a1 + " a.b2=" + (a == null ? "NPE" : a.b2) + " b=" + B2.b + " b1=" + B2.b1 + " b.a2=" + (B2.b == null ? "NPE" : B2.b.a2)); } } class B2 { static { System.out.println("Class B2 init start"); } static A2 b = new A2(); static int b1 = 3; { System.out.println("Instance B2 init start. b=" + b + " b1=" + b1 + " b.a2=" + (b == null ? "NPE" : b.a2) + " a=" + A2.a + " a1=" + A2.a1 + " a.b2=" + (A2.a == null ? "NPE" : A2.a.b2)); } public int b2 = 21; static { b1 = 4; System.out.println("Class B2 init end. b=" + b + " b1=" + b1 + " b.a2=" + (b == null ? "NPE" : b.a2) + " a=" + A2.a + " a1=" + A2.a1 + " a.b2=" + (A2.a == null ? "NPE" : A2.a.b2)); } { b2 = 22; System.out.println("Instance B2 init end. b=" + b + " b1=" + b1 + " b.a2=" + (b == null ? "NPE" : b.a2) + " a=" + A2.a + " a1=" + A2.a1 + " a.b2=" + (A2.a == null ? "NPE" : A2.a.b2)); } public B2() { System.out.println("Instance B2 new. b=" + b + " b1=" + b1 + " b.a2=" + (b == null ? "NPE" : b.a2) + " a=" + A2.a + " a1=" + A2.a1 + " a.b2=" + (A2.a == null ? "NPE" : A2.a.b2)); } } class Main2 { static public void main(String... args) { System.out.println("A2 a=" + A2.a); System.out.println("A2 a1=" + A2.a1); System.out.println("A2 a2=" + B2.b.a2); System.out.println("B2 b=" + B2.b); System.out.println("B2 b1=" + B2.b1); System.out.println("B2 b2=" + A2.a.b2); } }執(zhí)行結果分析
程序輸出結果:
1. [Loaded Main2 from file:/Users/jiadongy/JVM_Learning_Sample/out/production/JVM_Learning_Sample/] 2. [Loaded A2 from file:/Users/jiadongy/JVM_Learning_Sample/out/production/JVM_Learning_Sample/] 3. Class A2 init start 4. [Loaded B2 from file:/Users/jiadongy/JVM_Learning_Sample/out/production/JVM_Learning_Sample/] 5. Class B2 init start 6. Instance A2 init start. a=null a1=0 a.b2=NPE b=null b1=0 b.a2=NPE 7. Instance A2 init end. a=null a1=0 a.b2=NPE b=null b1=0 b.a2=NPE 8. Instance A2 new. a=null a1=0 a.b2=NPE b=null b1=0 b.a2=NPE 9. Class B2 init end. b=A2@61bbe9ba b1=4 b.a2=12 a=null a1=0 a.b2=NPE 10. Instance B2 init start. b=A2@61bbe9ba b1=4 b.a2=12 a=null a1=0 a.b2=NPE 11. Instance B2 init end. b=A2@61bbe9ba b1=4 b.a2=12 a=null a1=0 a.b2=NPE 12. Instance B2 new. b=A2@61bbe9ba b1=4 b.a2=12 a=null a1=0 a.b2=NPE 13. Class A2 init end. a=B2@610455d6 a1=2 a.b2=22 b=A2@61bbe9ba b1=4 b.a2=12 14. A2 a=B2@610455d6 15. A2 a1=2 16. A2 a2=12 17. B2 b=A2@61bbe9ba 18. B2 b1=4 19. B2 b2=22
把它轉化為下面的表格,更加清晰地描述A/B各個階段執(zhí)行的過程:
A | B |
---|---|
A類加載完成 | |
A類初始化 - 開始 | |
B類加載完成 | |
B類初始化 - 開始 | |
A類實例初始化 - 開始 | |
A類實例初始化 - 結束 | |
A類實例構造函數(shù)執(zhí)行完成 | |
B類初始化 - 結束 | |
B類實例初始化 - 開始 | |
B類實例初始化 - 結束 | |
B類實例構造函數(shù)執(zhí)行完成 | |
A類初始化 - 結束 |
可以看到在A類初始化的過程中,A類被實例化了(并且該階段正常結束了),也就是說類的初始化階段并不是原子的/排他的.
如在本例中,A類實例化階段的結束早于其類初始化階段,A類實例化完成時,A類的靜態(tài)變量還未被初始化.
Reference.1中已經(jīng)描述了這種情況:
總結_加載/驗證/準備/初始化和卸載這5個階段的順序是確定的_,類的加載過程必須按照這種順序按部就班的開始...注意,這里筆者寫的是按部就班的"開始",而不是按部就班的"進行"或"完成",強調這點是因為這些階段通都是相互交叉混合式進行的,通常會在一個階段執(zhí)行的過程中調用/激活另外一個階段
<<深入理解Java虛擬機>>P210
類的循環(huán)初始化不會引起死鎖
5個階段的開始是有順序的,結束則不一定
階段不是排他的/臨界的
循環(huán)初始化可能引起意料之外的情況,盡量避免
eg.類在初始化過程中修改另一個類的變量,導致另一個類得到了意料之外的初始值
Reference深入理解Java虛擬機
文章版權歸作者所有,未經(jīng)允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/67280.html
摘要:可能會持有相同的值對象但鍵對象必須是唯一的。當有新任務到達時,線程池沒有線程則創(chuàng)建線程處理,處理完成后該線程緩存秒,過期后回收,線程過期前有新任務到達時,則使用緩存的線程來處理。解決死鎖問題的三種方法預防死鎖檢測死鎖及避免死鎖。 最近辭職準備面試,順便整理一下面試題分享給大家,如有錯誤歡迎指出 01. 你對面向對象思想的理解? 面向對象編程簡稱OOP,是開發(fā)程序的一種方法、思想。面向...
摘要:近段時間在準備實習的面試,在網(wǎng)上看到一份面試題,就慢慢試著做,爭取每天積累一點點。現(xiàn)在每天給自己在面試題編寫的任務是題,有時候忙起來可能就沒有時間寫了,但是爭取日更,即使當天沒更也會在之后的更新補上。 ????近段時間在準備實習的面試,在網(wǎng)上看到一份面試題,就慢慢試著做,爭取每天積累一點點。????暫時手頭上的面試題只有一份,題量還是挺大的,有208題,所以可能講的不是很詳細,只是我自...
摘要:公平鎖非公平鎖公平鎖公平鎖是指多個線程按照申請鎖的順序來獲取鎖。加鎖后,任何其他試圖再次加鎖的線程會被阻塞,直到當前進程解鎖。重量級鎖會讓其他申請的線程進入阻塞,性能降低。 Java 中15種鎖的介紹 在讀很多并發(fā)文章中,會提及各種各樣鎖如公平鎖,樂觀鎖等等,這篇文章介紹各種鎖的分類。介紹的內容如下: 公平鎖 / 非公平鎖 可重入鎖 / 不可重入鎖 獨享鎖 / 共享鎖 互斥鎖 / 讀...
閱讀 1128·2021-08-12 13:24
閱讀 2974·2019-08-30 14:16
閱讀 3301·2019-08-30 13:01
閱讀 2064·2019-08-30 11:03
閱讀 2769·2019-08-28 17:53
閱讀 3079·2019-08-26 13:50
閱讀 2263·2019-08-26 12:00
閱讀 943·2019-08-26 10:38