眾所周知,Java是一門物件導向的語言,那麼一個物件在記憶體中都包含什麼東西呢,首先,物件大部分是儲存在堆上的(逃逸除外 )。
那麼物件儲存在堆中主要分為三個部分
#物件頭、物件實例資料、對齊補充(陣列會多一個陣列長度)
物件頭:
mark word: 儲存物件的hashCode、鎖定資訊(鎖定升級)或分代年齡或GC標誌等資訊
類型指針: 儲存指向物件所屬類別(元資料中class檔案)的指針,JVM通過這個確定這個物件屬於哪個類別
物件實例資料:
new出的物件訊息,存放類別的屬性資料訊息,包括父類別的屬性資訊;
對齊補充
數組物件會多對齊填滿
JVM要求物件佔用的空間必須是8 的倍數,方便記憶體分配(以位元組為最小單位分配),因此這部分就是用來填滿不夠的空間湊數用的。
#主流的存取方式主要有句柄與直接指標
句柄:在
Java堆中分割出一個記憶體作為句柄池,堆疊中的reference中儲存的事對象的句柄位址,而句柄中包含了物件實例資料與型別資料各自具體的位址資訊
#直接指標:
java堆中物件的記憶體佈局必須考慮如何防止存取類型資料的相關信息,reference中儲存的直接是物件位址。
直接指標存取物件不需要多一次間接存取開銷,而句柄方便在物件位址發生改變時(垃圾回收會移動物件位址)只需要改變句柄中的指標參考本身不需要改變。
虛擬機器遇到new指令時,先去檢查指定的類別是否被載入、驗證、準備(為類別中的所有靜態變數分配記憶體空間,並為其設定一個初始值 ) 、解析、初始化過。
類別檢查後虛擬機器為新物件分配記憶體
如何保證並發情況分配堆疊記憶體安全
虛擬機器採用CAS配上失敗重試保證原子性
把記憶體分配交給線程,在創建線程時分配空間,把分配記憶體的任務交給線程支配。透過TLAB(Thread local Allocation Buffer)開啟
分配完記憶體後設定物件頭,如哪個類別的實例、hashcode、類別的元資料資訊指標(方法區)
執⾏ init ⽅法(核心方法),初始化成員變量,執⾏實例化程式碼區塊,調⽤類別的建構⽅法,並把堆內物件的⾸位址賦值給引⽤變數。
#CAS 加失敗重試保證更新原⼦性。
把記憶體分配按線程劃分在不同空間,即每個線程在Java 堆中預先分配⼀⼩塊內存,叫做本地線程分配緩衝TLAB,哪個線程要分配內存就在對應的TLAB 分配,TLAB ⽤完了再進⾏同步。
父類別靜態成員和靜態初始化區塊,按在程式碼中出現的順序依序執行
子類別靜態成員和靜態初始化區塊,按在程式碼中出現的順序依次執行
父類別實例成員和實例初始化區塊,按在程式碼中出現的順序依序執行
父類別建構方法
#子類別實例成員和實例初始化區塊,按在程式碼中出現的順序依序執行
子類別建構方法
以上是Java物件儲存記憶體佈局的方法是什麼的詳細內容。更多資訊請關注PHP中文網其他相關文章!