前言
聊聊JVM,一個熟悉又陌生的名詞,從認識Java的第一天起,我們就會聽到這個名字,在參加工作的前一兩年,面試的時候還會經常被問到JDK,JRE,JVM這三者的區別。
JVM可以說和我們是老朋友了,但是在工作中的應用場景也許不如那些框架,但是在關鍵時候還是得靠它去搞定問題,俗話說得好,知己知彼,方能百戰不殆,JVM作爲前往高級工程師的一道坎,從這篇文章開始,我們會去逐步的分析,講解,攻克這座大山。
有關Java虛擬機類加載機制相關的文章一搜一大把,就也不必再贅述一遍了。在這裏撈出一道code題要各位大佬來把玩把玩,如果你一眼就看出了端倪,那麼恭喜你,你可以下山了:
問題:請問這段程序的輸出是什麼?
一般對於這類問題,小夥伴們腦海中肯定浮現出這樣的知識點
Java中賦值順序:
父類的靜態變量賦值
自身的靜態變量賦值
父類成員變量賦值和父類塊賦值
父類構造函數賦值
自身成員變量賦值和自身塊賦值
自身構造函數賦值
按照這個理論輸出是什麼呢?
答案輸出:1 4,這樣正確嚒?
肯定不正確啦,這裏不是說上面的規則不正確,而是說不能簡單的套用這個規則。正確的答案是:
有沒有答對呢?這裏主要的點之一:實例初始化不一定要在類初始化結束之後纔開始初始化。類的生命週期是:加載->驗證->準備->解析->初始化->使用->卸載,只有在準備階段和初始化階段纔會涉及類變量的初始化和賦值,因此只針對這兩個階段進行分析;
類的準備階段需要做是爲類變量分配內存並設置默認值,因此類變量st爲null、b爲0;(需要注意的是如果類變量是final,編譯時javac將會爲value生成ConstantValue屬性,在準備階段虛擬機就會根據ConstantValue的設置將變量設置爲指定的值,如果這裏這麼定義:static final int b=112,那麼在準備階段b的值就是112,而不再是0了。)
類的初始化階段需要做的是執行類構造器(類構造器是編譯器收集所有靜態語句塊和類變量的賦值語句按語句在源碼中的順序合併生成類構造器,對象的構造方法是(),類的構造方法是(),可以在堆棧信息中看到),因此先執行第一條靜態變量的賦值語句即st = new StaticTest (),此時會進行對象的初始化,對象的初始化是先初始化成員變量再執行構造方法,因此打印2->設置a爲110->執行構造方法(打印3,此時a已經賦值爲110,但是b只是設置了默認值0,並未完成賦值動作),等對象的初始化完成後繼續執行之前的類構造器的語句,接下來就不詳細說了,按照語句在源碼中的順序執行即可。
這裏面還牽涉到一個冷知識,就是在嵌套初始化時有一個特別的邏輯。特別是內嵌的這個變量恰好是個靜態成員,而且是本類的實例。這會導致一個有趣的現象:“實例初始化竟然出現在靜態初始化之前”。其實並沒有提前,你要知道java記錄初始化與否的時機。看一個簡化的代碼,把關鍵問題解釋清楚:
根據上面的代碼,有以下步驟:
首先在執行此段代碼時,首先由main方法的調用觸發靜態初始化。
在初始化Test 類的靜態部分時,遇到st這個成員。
但湊巧這個變量引用的是本類的實例。
那麼問題來了,此時靜態初始化過程還沒完成就要初始化實例部分了。是這樣麼?
從人的角度是的。但從java的角度,一旦開始初始化靜態部分,無論是否完成,後續都不會再重新觸發靜態初始化流程了。
因此在實例化st變量時,實際上是把實例初始化嵌入到了靜態初始化流程中,並且在樓主的問題中,嵌入到了靜態初始化的起始位置。這就導致了實例初始化完全至於靜態初始化之前。這也是導致a有值b沒值的原因。
最後再考慮到文本順序,結果就顯而易見了。
詳細看到這裏,心中大概有個結論了吧。
這是20道面試官經常問的JVM面試題,看一看你會幾道?
1. 內存模型以及分區,需要詳細到每個區放什麼。
2. 堆裏面的分區:Eden,survival (from+ to),老年代,各自的特點。
3. 對象創建方法,對象的內存分配,對象的訪問定位。
4. GC 的兩種判定方法:
5. SafePoint 是什麼
6. GC 的三種收集方法:標記清除、標記整理、複製算法的原理與特點,分別用在什麼地方,如果讓你優化收集方法,有什麼思路?
7. GC 收集器有哪些?CMS 收集器與 G1 收集器的特點。
8. Minor GC 與 Full GC 分別在什麼時候發生?
9. 幾種常用的內存調試工具:jmap、jstack、jconsole、jhat
10. 類加載的幾個過程:
11.JVM 內存分哪幾個區,每個區的作用是什麼?
12.如和判斷一個對象是否存活?(或者 GC 對象的判定方法)
13.簡述 java 垃圾回收機制?
14.java 中垃圾收集的方法有哪些?
15.java 內存模型
16.java 類加載過程?
17. 簡述 java 類加載機制?
18. 類加載器雙親委派模型機制?
19.什麼是類加載器,類加載器有哪些?
20.簡述 java 內存分配與回收策率以及 Minor GC 和Major GC
最後
歡迎大家一起交流,喜歡文章記得關注我,點個喜歡喲,感謝支持!