一個對象實例佔用了多少字節,消耗了多少內存?這樣的問題在c或c++裏使用sizeof()方法就可以得到明確答案,在java裏好像沒有這樣的方法(java一樣可以實現),不過通過jmap工具倒是可以查看出一個對象的佔用內存的大小,這裏介紹一種通過分析java代碼計算內存使用情況的方法。
注意,一下討論的情況都是基於32位機,不適用用64位機,JVM是sun的HotSpot,不同的虛擬機實現可能會不同
規則一:每個對象被按照8bytes粒度對齊(數組除外)
在jvm中每個對象(數組除外)都有一個頭,這個頭有兩個字,第一個字存儲的時對象的一些標誌位信息,例如:鎖標誌位、經歷了幾次gc等信息,第二個字是一個引用,指向了這個類的類信息。這裏jvm給這兩個字留了8個字節的空間(這個爲啥用8個字節空間不是很清楚,一個字即兩個字節,我一直認爲4個字節就夠了)
按規則一:new Object();這個Object實例就佔用了8個字節
規則二:爲類屬性分配存儲空間時不是按照類中定義的屬性順序,而是按如下的順序:
1、double\long;----8bytes
2、int\float;----4bytes
3、char\short;----2bytes
4、boolean\byte;----1bytes
5、reference;----4bytes
例如:
- public class A {
- byte a;
- char b;
- int c;
- long d;
- Object e;
- }
屬性 | 需要字節數 | 累積字節數 |
header | 8bytes | 8 |
long:d | 8bytes | 16 |
int:c | 4bytes | 20 |
char:b | 2bytes | 22 |
byte:a | 1bytes | 23 |
Object:e | 4bytes | 27 |
padding 5bytes | 32 |
最後一行padding 5bytes的目的是,規則一中描述每個對象按照8個字節的粒度對齊,這樣下一個分配的對象的開始位置必須在8的倍數上,而離27最近的8的倍數是32,因此加了5bytes。A佔用32bytes
可以用jmap看一下這個計算是否準確
規則三:對於繼承時,要按照規則二先計算父類的類屬性佔用情況,再按照規則二計算子類的類屬性佔用情況,不能將父類和子類的屬性混合在一起按規則二分配。
例如:
- class B{
- long a;
- int b;
- int c;
- }
- class BB extends B{
- long d;
- }
屬性 | 佔用字節數 | 累計字節數 |
header | 8 | 8 |
a | 8 | 16 |
b | 4 | 20 |
c | 4 | 24 |
d | 8 | 32 |
這裏累計字節正好是8的倍數,滿足規則一,因此不用padding字節。BB對象內存佔用了32bytes
規則四:父類的最後一個屬性和子類第一個屬性必須按4個字節的倍數對齊
例如:
- class B{
- long a;
- int b;
- char c;
- }
- class BB extends B{
- long d;
- }
屬性 | 佔用的字節 | 累計字節 |
head | 8 | 8 |
a | 8 | 16 |
c | 2 | 18 |
padding 2 | 20 | |
d | 8 | 28 |
padding 4 | 32 |
第一次padding2是因爲屬性c分配內存後,不滿足父類最後一個屬性和子類第一個屬性按4字節粒度對齊(18除4除不開),因此需要添加兩個字節使其可以按4字節粒度對齊。
第二次paadding4是依據規則一
規則五:當子類的第一個屬性是double或long,但是父類不能按8字節粒度對齊時,子類內存分配時的順序將不按規則二進行,而是按:先int\float、char\short、boolean\byte、reference、long\double
例如:
- class A{
- byte a;
- }
- class B extends A{
- long b;
- short c;
- byte d;
- }
屬性 | 佔用字節數 | 累計佔用字節數 |
head | 8 | 8 |
a | 1 | 9 |
padding 3 | 12 | |
c | 2 | 14 |
d | 1 | 15 |
padding 1 | 16 | |
b | 8 | 24 |
第一次 padding 3是根據規則四
第二次 padding 1是因爲b屬性是8個字節,因此需要按8個字節粒度對齊。B佔用24bytes
對於數組,與普通對象不同的是在頭部,頭部多了4個字節用於存儲長度信息。因此數組的head是12bytes而不是8bytes