Java對象內存佔用情況分析

一個對象實例佔用了多少字節,消耗了多少內存?這樣的問題在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

例如:

Java代碼  收藏代碼
  1. public class A {   
  2.     byte a;   
  3.     char b;   
  4.     int c;   
  5.     long d;   
  6.     Object e;   
  7. }   

 

 

 

屬性 需要字節數 累積字節數
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看一下這個計算是否準確

 

規則三:對於繼承時,要按照規則二先計算父類的類屬性佔用情況,再按照規則二計算子類的類屬性佔用情況,不能將父類和子類的屬性混合在一起按規則二分配。

例如:

Java代碼  收藏代碼
  1. class B{  
  2.     long a;  
  3.     int b;  
  4.     int c;  
  5. }  
  6.   
  7. class BB extends B{  
  8.     long d;  
  9. }  

 

 屬性 佔用字節數 累計字節數
header 8 8
a 8 16
b 4 20
c 4 24
d 8 32

 

這裏累計字節正好是8的倍數,滿足規則一,因此不用padding字節。BB對象內存佔用了32bytes

 

規則四:父類的最後一個屬性和子類第一個屬性必須按4個字節的倍數對齊

例如:

Java代碼  收藏代碼
  1. class B{  
  2.     long a;  
  3.     int b;  
  4.     char c;  
  5. }  
  6.   
  7. class BB extends B{  
  8.     long d;  
  9. }  

 

 

屬性 佔用的字節 累計字節
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

 

例如:

Java代碼  收藏代碼
  1. class A{  
  2.     byte a;  
  3. }  
  4.   
  5. class B extends A{  
  6.     long b;  
  7.     short c;  
  8.     byte d;  
  9. }  

 

 

屬性 佔用字節數 累計佔用字節數
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

 

發佈了21 篇原創文章 · 獲贊 28 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章