您好,登錄后才能下訂單哦!
這期內容當中小編將會給大家帶來有關怎么深入理解Java 虛擬機中的HotSpot虛擬機對象,文章內容豐富且以專業的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。
在 HotSpot 虛擬機中,對象的內存布局分為以下 3 塊區域:
對象頭(Header)
實例數據(Instance Data)
對齊填充(Padding)
對象頭記錄了對象在運行過程中所需要使用的一些數據:
哈希碼
GC 分代年齡
鎖狀態標志
線程持有的鎖
偏向線程 ID
偏向時間戳
對象頭可能包含類型指針,通過該指針能確定對象屬于哪個類。如果對象是一個數組,那么對象頭還會包括數組長度。
實例數據部分就是成員變量的值,其中包括父類成員變量和本類成員變量。
用于確保對象的總長度為 8 字節的整數倍。
HotSpot VM 的自動內存管理系統要求對象的大小必須是 8 字節的整數倍。而對象頭部分正好是 8 字節的倍數(1 倍或 2 倍),因此,當對象實例數據部分沒有對齊時,就需要通過對齊填充來補全。
對齊填充并不是必然存在,也沒有特別的含義,它僅僅起著占位符的作用。
虛擬機在解析 .class
文件時,若遇到一條 new 指令,首先它會去檢查常量池中是否有這個類的符號引用,并且檢查這個符號引用所代表的類是否已被加載、解析和初始化過。如果沒有,那么必須先執行相應的類加載過程。
對象所需內存的大小在類加載完成后便可完全確定,接下來從堆中劃分一塊對應大小的內存空間給新的對象。分配堆中內存有兩種方式:
指針碰撞
如果 Java 堆中內存絕對規整(說明采用的是“復制算法”或“標記整理法”),空閑內存和已使用內存中間放著一個指針作為分界點指示器,那么分配內存時只需要把指針向空閑內存挪動一段與對象大小一樣的距離,這種分配方式稱為“指針碰撞”。
空閑列表
如果 Java 堆中內存并不規整,已使用的內存和空閑內存交錯(說明采用的是標記-清除法,有碎片),此時沒法簡單進行指針碰撞, VM 必須維護一個列表,記錄其中哪些內存塊空閑可用。分配之時從空閑列表中找到一塊足夠大的內存空間劃分給對象實例。這種方式稱為“空閑列表”。
分配完內存后,為對象中的成員變量賦上初始值,設置對象頭信息,調用對象的構造函數方法進行初始化。
至此,整個對象的創建過程就完成了。
所有對象的存儲空間都是在堆中分配的,但是這個對象的引用卻是在堆棧中分配的。也就是說在建立一個對象時兩個地方都分配內存,在堆中分配的內存實際建立這個對象,而在堆棧中分配的內存只是一個指向這個堆對象的指針(引用)而已。 那么根據引用存放的地址類型的不同,對象有不同的訪問方式。
堆中需要有一塊叫做“句柄池”的內存空間,句柄中包含了對象實例數據與類型數據各自的具體地址信息。
引用類型的變量存放的是該對象的句柄地址(reference)。訪問對象時,首先需要通過引用類型的變量找到該對象的句柄,然后根據句柄中對象的地址找到對象。
直接指針訪問方式
引用類型的變量直接存放對象的地址,從而不需要句柄池,通過引用能夠直接訪問對象。但對象所在的內存空間需要額外的策略存儲對象所屬的類信息的地址。
需要說明的是,HotSpot 采用第二種方式,即直接指針方式來訪問對象,只需要一次尋址操作,所以在性能上比句柄訪問方式快一倍。但像上面所說,它需要額外的策略來存儲對象在方法區中類信息的地址。
上述就是小編為大家分享的怎么深入理解Java 虛擬機中的HotSpot虛擬機對象了,如果剛好有類似的疑惑,不妨參照上述分析進行理解。如果想知道更多相關知識,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。