摘要:由于的自動內存管理系統要求對象起始地址必須是字節的整數倍,換句話說,就是對象的大小必須是字節的整數倍。對象大小計算要點在位系統下,存放指針的空間大小是字節,是字節,對象頭為字節。靜態屬性不算在對象大小內。
jvm系列
垃圾回收基礎
JVM的編譯策略
GC的三大基礎算法
GC的三大高級算法
GC策略的評價指標
JVM信息查看
GC通用日志解讀
jvm的card table數據結構
Java類初始化順序
Java對象結構及大小計算
Java的類加載機制
Java對象分配簡要流程
年老代過大有什么影響
Survivor空間溢出實例
關于Object=null
Java線程與Xss
序本文主要簡述Java對象的內存布局以及其大小的計算。
Java對象內存布局在HotSpot虛擬機中,對象在內存中存儲的布局可以分為3塊區域:對象頭(Header)、實例數據(Instance Data)和對齊填充(Padding)。
對象頭HotSpot虛擬機的對象頭包括兩部分信息:
第一部分markword,用于存儲對象自身的運行時數據,如哈希碼(HashCode)、GC分代年齡、鎖狀態標志、線程持有的鎖、偏向線程ID、偏向時間戳等,這部分數據的長度在32位和64位的虛擬機(未開啟壓縮指針)中分別為32bit和64bit,官方稱它為“MarkWord”。
對象頭的另外一部分是klass,類型指針,即對象指向它的類元數據的指針,虛擬機通過這個指針來確定這個對象是哪個類的實例.
實例數據實例數據部分是對象真正存儲的有效信息,也是在程序代碼中所定義的各種類型的字段內容。無論是從父類繼承下來的,還是在子類中定義的,都需要記錄起來。
對齊填充第三部分對齊填充并不是必然存在的,也沒有特別的含義,它僅僅起著占位符的作用。由于HotSpot VM的自動內存管理系統要求對象起始地址必須是8字節的整數倍,換句話說,就是對象的大小必須是8字節的整數倍。而對象頭部分正好是8字節的倍數(1倍或者2倍),因此,當對象實例數據部分沒有對齊時,就需要通過對齊填充來補全。
對象大小計算 要點在32位系統下,存放Class指針的空間大小是4字節,MarkWord是4字節,對象頭為8字節。
在64位系統下,存放Class指針的空間大小是8字節,MarkWord是8字節,對象頭為16字節。
64位開啟指針壓縮的情況下,存放Class指針的空間大小是4字節,MarkWord是8字節,對象頭為12字節。
數組長度4字節+數組對象頭8字節(對象引用4字節(未開啟指針壓縮的64位為8字節)+數組markword為4字節(64位未開啟指針壓縮的為8字節))+對齊4=16字節。
靜態屬性不算在對象大小內。
實例import java.util.HashMap; /** * 64位開啟指針壓縮的話,markword變成8字節,壓縮了class指針為4字節,故對象頭12字節 * 64位沒有開啟指針壓縮的話,markword8字節,class指針8字節,對象頭16字節 * 32位markword為4字節,class指針為4字節,對象頭8字節 * * 另外,靜態屬性所占用的空間通常不算在對象本身,因為它的引用是在方法區。 * * @author xixicat * @created 2014-10-03 */ public class ObjectSize { public static void main(String[] args){ System.out.println(SizeOfTool.getObjectSize(new A(),SizeEnum.B)); System.out.println(SizeOfTool.getObjectSize(new B(),SizeEnum.B)); System.out.println(SizeOfTool.getObjectSize(new C(),SizeEnum.B)); System.out.println(SizeOfTool.getObjectSize(new D(),SizeEnum.B)); System.out.println(SizeOfTool.getObjectSize(new E(),SizeEnum.B)); System.out.println(SizeOfTool.getObjectSize(new Q(),SizeEnum.B)); /** * 64位壓縮指針下,對象頭12字節,數組長度描述4字節,數據4*100 =16+400 = 416 */ System.out.println(SizeOfTool.getObjectSize(new int[100],SizeEnum.B)); /** * 屬性4位對齊 * 64位壓縮指針下,對象頭12字節,數組長度描述4字節,數據1*100,對齊后104 = 16+104 = 120 */ System.out.println(SizeOfTool.getObjectSize(new byte[100],SizeEnum.B)); /** * 二維數組 * 64位指針壓縮下 * 第1維數組,對象頭12字節,數組長度描述4字節,2個數組引用共8字節,共24字節 * 第2維數組,對象頭12字節,數組長度描述4字節,100個數組引用共400字節,對齊后共416字節 * 第1維的2個引用所指對象大小 = 2*416 = 832 字節 * 共24+832 = 856字節 */ System.out.println(SizeOfTool.getObjectSize(new int[2][100],SizeEnum.B)); /** * 二維數組 * 64位指針壓縮下 * 第1維數組,對象頭12字節,數組長度描述4字節,100個數組引用共400字節,共416字節 * 第2維數組,對象頭12字節,數組長度描述4字節,2個數組引用共8字節,共24字節 * 第1維的100個引用所指對象大小 = 100*24 = 2400 字節 * 共416+2400 = 2816字節 */ System.out.println(SizeOfTool.getObjectSize(new int[100][2],SizeEnum.B)); System.out.println(SizeOfTool.getObjectSize(new Object(),SizeEnum.B)); /** * 不算static屬性 * private final char value[]; * private int hash; // Default to 0 * private transient int hash32 = 0; * * 32位下,String對象頭8字節,2個int類型8字節,char數組引用占4字節,共占24字節 * 另外,還要算上value[]數組的占用,數組對象頭部8字節,數組長度4字節,對齊后共占16字節 * =》String對象對象大小24+16 = 40字節 * 64位開啟指針壓縮下(壓縮指針),String對象頭12字節,2個int類型8字節,char數組引用占4字節,共占24字節 * 另外,還要算上value[]數組的占用,數組對象頭部12字節,數組長度4字節,對齊后共占16字節 * =》String對象大小24+16=40字節 */ System.out.println(SizeOfTool.getObjectSize(new String(),SizeEnum.B)); /** * transient Entry參考[] table = (Entry []) EMPTY_TABLE; * transient int size; * int threshold; * final float loadFactor; * transient int modCount; * * 64位開啟指針壓縮下,對象頭部12字節,數組引用4字節,3個int12字節,float4字節,共32字節 * 另外,算上Entry [] = 對象頭12 +屬性16字節+數組長度4字節 = 32字節 * * final K key; * V value; * Entry next; * int hash; * * 對象頭12字節,3個引用共12字節,1個int4字節 =》 一個entry至少占用28字節 * * =》32+32=64字節 */ System.out.println(SizeOfTool.getObjectSize(new HashMap(),SizeEnum.B)); } } //32位下對象頭8字節,byte占1字節,對其填充后,總占16字節 //64位開啟指針壓縮下對象頭12字節,byte1字節,對齊后占16字節 class A{ byte b1; } //32位下對象頭8字節,8個byte8字節,總16字節 //64位開啟指針壓縮下對象頭12字節,8個byte8字節,對齊后占24字節 class B{ byte b1,b2,b3,b4,b5,b6,b7,b8; } //32位下對象頭8字節,9個byte9字節,對其填充后,總24字節 //64位開啟指針壓縮下對象頭12字節,9個byte9字節,對齊后占24字節 class C{ byte b1,b2,b3,b4,b5,b6,b7,b8,b9; } //32位下對象頭8字節,int占4字節,引用占4字節,共16字節 //64位開啟指針壓縮下對象頭12字節,int占4字節,引用占4字節,對齊后占24字節 class D{ int i; String str; } //32位下對象頭8字節,int4字節,byte占1字節,引用占4字節,對其后,共24字節 //64位開啟指針壓縮下對象頭12字節,int占4字節,引用占4字節,byte占1字節,對齊后占24字節 class E{ int i; byte b; String str; } /** * 對齊有兩種 * 1、整個對象8字節對齊 * 2、屬性4字節對齊 **** * * 對象集成屬性的排布 * markword 4 8 * class指針 4 4 * 父類的父類屬性 1 1 * 屬性對齊 3 3 * 父類的屬性 1 1 * 屬性對齊 3 3 * 當前類的屬性 1 1 * 屬性對齊填充 3 3 * 整個對象對齊 8+12 =》 24 12+12=》24 */ class O{ byte b; } class P extends O{ byte b; } class Q extends P{ byte b; }
深入理解Java虛擬機(第2版)
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/65601.html
摘要:對于不同的實現,對象占用的內存空間大小可能不盡相同,本文主要分析中的情況,實驗環境為位系統,使用進行結論驗證。內存占用這里分析一個只有一組鍵值對的結構如下首先分析本身的大小。 本文深入分析并驗證了不同Java對象占用內存空間大小的情況。對于不同的jvm實現,Java對象占用的內存空間大小可能不盡相同,本文主要分析HotSpot jvm中的情況,實驗環境為64位window10系統、JD...
摘要:下面是線程相關的熱門面試題,你可以用它來好好準備面試。線程安全問題都是由全局變量及靜態變量引起的。持有自旋鎖的線程在之前應該釋放自旋鎖以便其它線程可以獲得自旋鎖。 最近看到網上流傳著,各種面試經驗及面試題,往往都是一大堆技術題目貼上去,而沒有答案。 不管你是新程序員還是老手,你一定在面試中遇到過有關線程的問題。Java語言一個重要的特點就是內置了對并發的支持,讓Java大受企業和程序員...
摘要:本文詳細描述了堆內存模型,垃圾回收算法以及處理內存泄露的最佳方案,并輔之以圖表,希望能對理解內存結構有所幫助。該區域也稱為內存模型的本地區。在中,內存泄露是指對象已不再使用,但垃圾回收未能將他們視做不使用對象予以回收。 本文詳細描述了 Java 堆內存模型,垃圾回收算法以及處理內存泄露的最佳方案,并輔之以圖表,希望能對理解 Java 內存結構有所幫助。原文作者 Sumith Puri,...
摘要:在一般應用中,不會逃逸的局部對象所占的比例很大,如果能使用棧上分配,那大量的對象就會隨著方法的結束而自動銷毀了,垃圾收集系統的壓力將會小很多。相關參數設置大對象直接進入年老代的閾值,當對象大小超過這個值時,將直接在年老代分配。 jvm系列 垃圾回收基礎 JVM的編譯策略 GC的三大基礎算法 GC的三大高級算法 GC策略的評價指標 JVM信息查看 GC通用日志解讀 jvm的card t...
閱讀 3925·2021-10-12 10:12
閱讀 2886·2021-09-10 11:18
閱讀 3673·2019-08-30 15:54
閱讀 2808·2019-08-30 15:53
閱讀 638·2019-08-30 13:54
閱讀 965·2019-08-30 13:21
閱讀 2260·2019-08-30 12:57
閱讀 1687·2019-08-30 11:10