Java 物件的生命週期
類的建立階段的詳細流程
-
第一步:找到需要載入的類並把類的資訊載入到jvm的方法區中。載入的方式有如下:
-
從class檔案中讀取
-
從jar檔案中讀取
-
從網路獲取applet
-
根據一定的規則生成:比如動態代理模式,自動生成的程式碼
-
從非class檔案中讀取:道理和從class檔案中讀取一個道理
載入的時機分為 預載入和延遲載入兩種,hotspot就是延遲載入
-
-
第二步:連結 一般與載入過程交叉進行,可細分為三個步驟
-
驗證:驗證載入的類時候合法
-
準備:為靜態變數分配記憶體,並設定為JVM初始值(非程式碼設定初始值)。常量設定為程式碼設定的預設值
-
解析:jvm會將所有的類或介面名、欄位名、方法名轉換為具體的記憶體地址
連線階段完成之後會根據使用的情況(直接引用還是被動引用)來選擇是否對類進行初始化
-
-
第三步:如果一個類被直接引用,就會觸發類的初始化。以下幾種狀態稱為直接引用
-
通過new關鍵字例項化物件、讀取或設定類的靜態變數、呼叫類的靜態方法
-
通過反射方式執行以上三種行為
-
初始化子類的時候會觸發父類的初始化
-
作為程式的入口直接執行(main方法)
類的初始化過程是這樣的:按照順序自上而下執行類中的靜態變數賦值語句和靜態語句,如果有父類,則首先按照順序執行父類中的靜態變數賦值語句和靜態語句
陣列宣告屬於被動引用,不會觸發初始化
-
物件分為
1.建立階段(Created)
JVM 載入類的class檔案 此時所有的static變數和static程式碼塊將被執行
載入完成後,對區域性變數進行賦值(先父後子的順序)
再執行new方法 呼叫建構函式
一旦物件被建立,並被分派給某些變數賦值,這個物件的狀態就切換到了應用階段
2.應用階段(In Use)
物件至少被一個強引用持有著
3.不可見階段(Invisible)
當一個物件處於不可見階段時,說明程式本身不再持有該物件的任何強引用,雖然該這些引用仍然是存在著的。
簡單說就是程式的執行已經超出了該物件的作用域了
4.不可達階段(Unreachable)
物件處於不可達階段是指該物件不再被任何強引用所持有。
與“不可見階段”相比,“不可見階段”是指程式不再持有該物件的任何強引用,這種情況下,該物件仍可能被JVM等系統下的某些已裝載的靜態變數或執行緒或JNI等強引用持有著,這些特殊的強引用被稱為”GC root”。存在著這些GC root會導致物件的記憶體洩露情況,無法被回收
5.收集階段(Collected)
當垃圾回收器發現該物件已經處於“不可達階段”並且垃圾回收器已經對該物件的記憶體空間重新分配做好準備時,則物件進入了“收集階段”。如果該物件已經重寫了finalize()方法,則會去執行該方法的終端操作
6.終結階段(Finalized)
當物件執行完finalize()方法後仍然處於不可達狀態時,則該物件進入終結階段。在該階段是等待垃圾回收器對該物件空間進行回收
7.物件空間重分配階段(De-allocated)
垃圾回收器對該物件的所佔用的記憶體空間進行回收或者再分配了,則該物件徹底消失了,稱之為“物件空間重新分配階段