參考博文: http://www.javamex.com/tutorials/memory/object_memory_usage.shtmlhtml
本文主要考慮正常狀況下一個對象在堆上的內存佔用狀況:對於下面的特殊狀況不做討論java
一、某些狀況下,JVM可能不會把對象存儲在堆上:好比小的線程私有對象原則上會所有存儲在棧或寄存器上,嚴格意義上說並不存在於java堆上android
二、對象的內存佔用可能依賴於它當前的狀態,好比說它的同步鎖是否處於競爭狀態、是否正處於垃圾回收階段(這些額外的「系統」數據不必定存儲在java堆上)數組
在HotSpot虛擬機上,一個java對象的內存佔用通常包括以下幾部分:ide
一、一個對象頭部信息(包括幾字節的基本元信息)post
二、原始類型字段的內存佔用spa
三、引用字段的內存佔用.net
四、對齊字節(padding):爲了讓每一個對象的開始地址是字節的整數倍,減小對象指針佔用的比特數,對象數據後面會添加一些「無用」的數據(字節),以實現對齊,即保證最終的字節大小是8的倍數線程
HotSpot虛擬機的對象頭包含兩部分信息:一、用於存儲對象自身的運行時數據,這部分數據在32位和64位的虛擬機(未開啓壓縮指針)中分別爲32bit和64bit。3d
二、類型指針,即對象指向它的類元數據的指針,虛擬機經過這個指針來肯定這個對象是哪一個類的實例。注:若是java對象是一個數組,還必須包含用於記錄數組長度的數據,由於java虛擬機能夠從普通java對象的元數據信息肯定對象的大小,可是從數組的元數據中卻沒法肯定數組的大小。
下圖描述了32bit下對象頭的存儲狀態:
實例數據部分是對象真正存儲的有效信息:也即程序代碼定義的各類類型的字段內容。
這部分的存儲順序會受到虛擬機的的分配策略參數和字段在java源碼中定義的順序的影響。
java元數據類型佔用字節列表:
可能會認爲boolean會佔用一比特或者佔用一個字節的第八位,可是HotSpot虛擬機會爲每一個Boolean字段分配一個字節的空間。
在HotSpot中,每一個對象佔用的內存大小是 8 字節的倍數。若是對象所需的內存大小(包括頭信息和字段)不是 8 的倍數,則會向上取整到 8 的倍數。
也就是說:
一、一個空對象佔用8字節
二、只有一個 boolean 字段的類實例佔 16 字節:頭信息佔 8 字節,boolean 佔 1 字節,爲了對齊達到 8 的倍數會額外佔用 7 個字節
三、包含 8 個 boolean 字段的實例也會佔用 16 字節:頭信息佔用 8 字節,boolean 佔用 8 字節;由於已是 8 的倍數,不須要補充額外的數據來對齊
四、一個包含 2 個 long 字段、3 個 int 字段、1 個 boolean 字段的對象將佔用:
關於二維數組佔用字節數計算:注意數組有一個不一樣的地方在於,它自己會有一個記錄數組長度的int類型,佔用4字節,自己又是一個對象,會佔用8字節
For example, let's consider a 10x10 int array. Firstly, the "outer" array has its 12-byte object header followed by space for the 10 elements. Those elements are object references to the 10 arrays making up the rows. That comes to 12+4*10=52 bytes, which must then be rounded up to the next multiple of 8, giving 56. Then, each of the 10 rows has its own 12-byte object header, 4*10=40 bytes for the actual row of ints, and again, 4 bytes of padding to bring the total for that row to a multiple of 8. So in total, that gives 11*56=616 bytes. That's a bit bigger than if you'd just counted on 10*10*4=400 bytes for the hundred "raw" ints themselves.
關於java內存佔用更爲詳細的描述能夠參考廖祜秋大神的博客:http://www.liaohuqiu.net/cn/posts/caculate-object-size-in-java/
廖神的博文中已經指出對於HotSpot,在32位的JVM中,一個對象引用佔用4字節,而在64位的JVM中,一個對象引用佔用8字節(在開啓指針壓縮的話佔用4字節),而在Dalvik中則是始終佔用4字節。
針對Dalvik,元數據類型的大小分別在做爲對象域或變量,以及數組的一個元素時是不一樣的
在Dalvik中對象對齊邊界也是8字節,可是一個對象的內存佔用和HotSpot是不一樣的:
會有一個額外的dlmalloc空間佔用,4或8字節
因此一個空對象會佔用16字節(12字節的內存佔用以及4字節的對齊)
示例演示:
class EmptyClass { }
Total size: 8 (Object overhead) + 4 (dlmalloc) = 12 bytes. For 8 bytes alignment, the final total size is 16 bytes.
class Integer { int value; // 4 bytes }
The total size is: 8 + 4 + 4 (int) = 16 bytes.
static class HashMapEntry<K, V> { final K key; // 4 bytes final int hash; // 4 bytes V value; // 4 bytes HashMapEntry<K, V> next; // 4 bytes }
The total size: 8 + 4 + 4 * 4 = 28 bytes. Total aligned is 32 bytes.
詳細描述參考廖神博文:http://www.liaohuqiu.net/posts/android-object-size-dalvik/