无招胜有招之Java进阶JVM(七)对象模型
?
Java對象前言:
在jvm的內存結構中,對象保存在堆中,而我們在對對象進行操作時,其實操作的是對象的引用。
?
Java對象包含三個部分:
一個Java對象可以分為三部分存儲在內存中,分別是:對象頭(Header)、實例數據(Instance Data)和對齊填充(Padding)。
1.對象頭(包含鎖狀態標志,線程持有的鎖等標志)
2.實例數據
3.對齊填充
對象頭:對象頭包括兩部分信息分別是Mark World和元數據指針,Mark World用于存儲對象運行時的數據,比如HashCode、鎖狀態標志、GC分代年齡等。而元數據指針用于指向方法區的中目標類的類型信息,通過元數據指針可以確定對象的具體類型。
實例數據:用于存儲對象中的各種類型的字段信息(包括從父類繼承來的)。
對齊填充:對齊填充不一定存在,起到了占位符的作用,沒有特別的含義。
?
OOP-Klass:
HotSpot中采用了OOP-Klass模型,它是用來描述Java對象實例的一種模型,OOP(Ordinary Object Pointer)指的是普通對象指針,而Klass用來描述對象實例的具體類型。
?
【補充】
在Java中,對象的生命周期包括以下幾個階段:
1.??????創建階段(Created)
2.??????應用階段(In Use)
3.??????不可見階段(Invisible)
4.??????不可達階段(Unreachable)
5.??????收集階段(Collected)
6.??????終結階段(Finalized)
7.??????對象空間重分配階段(De-allocated)
1.創建階段(Created)
在創建階段系統通過下面的幾個步驟來完成對象的創建過程
l? 為對象分配存儲空間
l? 開始構造對象
l? 從超類到子類對static成員進行初始化
l? 超類成員變量按順序初始化,遞歸調用超類的構造方法
l? 子類成員變量按順序初始化,子類構造方法調用
一旦對象被創建,并被分派給某些變量賦值,這個對象的狀態就切換到了應用階段
?
2.應用階段(In Use)
對象至少被一個強引用持有著。
?
3.不可見階段(Invisible)
當一個對象處于不可見階段時,說明程序本身不再持有該對象的任何強引用,雖然該這些引用仍然是存在著的。
簡單說就是程序的執行已經超出了該對象的作用域了。
舉例如下圖:本地變量count在25行時已經超出了其作用域,則在此時稱之為count處于不可視階段。當然這種情況編譯器在編譯的過程中會直接報錯了。
圖2. 不可見階段示例
4.不可達階段(Unreachable)
對象處于不可達階段是指該對象不再被任何強引用所持有。
與“不可見階段”相比,“不可見階段”是指程序不再持有該對象的任何強引用,這種情況下,該對象仍可能被JVM等系統下的某些已裝載的靜態變量或線程或JNI等強引用持有著,這些特殊的強引用被稱為”GC root”。存在著這些GC root會導致對象的內存泄露情況,無法被回收。
?
5.收集階段(Collected)
當垃圾回收器發現該對象已經處于“不可達階段”并且垃圾回收器已經對該對象的內存空間重新分配做好準備時,則對象進入了“收集階段”。如果該對象已經重寫了finalize()方法,則會去執行該方法的終端操作。
這里要特別說明一下:不要重載finazlie()方法!原因有兩點:
l? 會影響JVM的對象分配與回收速度
在分配該對象時,JVM需要在垃圾回收器上注冊該對象,以便在回收時能夠執行該重載方法;在該方法的執行時需要消耗CPU時間且在執行完該方法后才會重新執行回收操作,即至少需要垃圾回收器對該對象執行兩次GC。
l? 可能造成該對象的再次“復活”
在finalize()方法中,如果有其它的強引用再次持有該對象,則會導致對象的狀態由“收集階段”又重新變為“應用階段”。這個已經破壞了Java對象的生命周期進程,且“復活”的對象不利用后續的代碼管理。
?
6.終結階段
當對象執行完finalize()方法后仍然處于不可達狀態時,則該對象進入終結階段。在該階段是等待垃圾回收器對該對象空間進行回收。
?
7.對象空間重新分配階段
垃圾回收器對該對象的所占用的內存空間進行回收或者再分配了,則該對象徹底消失了,稱之為“對象空間重新分配階段”。
摘自:https://blog.csdn.net/moneyshi/article/details/53033578
總結
以上是生活随笔為你收集整理的无招胜有招之Java进阶JVM(七)对象模型的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 大剑无锋之HashMap全考点
- 下一篇: 无招胜有招之Java进阶JVM(八)类加