电竞比分网-中国电竞赛事及体育赛事平台

分享

java jvm字節(jié)占用空間分析

 codingparty 2016-01-11

 

一個對象實例占用了多少字節(jié),消耗了多少內(nèi)存?這樣的問題在c或c++里使用sizeof()方法就可以得到明確答案,在java里好像沒有這樣的方法(java一樣可以實現(xiàn)),不過通過jmap工具倒是可以查看出一個對象的占用內(nèi)存的大小,這里介紹一種通過分析java代碼計算內(nèi)存使用情況的方法。

注意,一下討論的情況都是基于32位機(jī),不適用用64位機(jī),JVM是sun的HotSpot,不同的虛擬機(jī)實現(xiàn)可能會不同

 

規(guī)則一:每個對象被按照8bytes粒度對齊(數(shù)組除外)

 

在jvm中每個對象(數(shù)組除外)都有一個頭,這個頭有兩個字,第一個字存儲的時對象的一些標(biāo)志位信息,例如:鎖標(biāo)志位、經(jīng)歷了幾次gc等信息,第二個字是一個引用,指向了這個類的類信息。這里jvm給這兩個字留了8個字節(jié)的空間(這個為啥用8個字節(jié)空間不是很清楚,一個字即兩個字節(jié),我一直認(rèn)為4個字節(jié)就夠了)

按規(guī)則一:new Object();這個Object實例就占用了8個字節(jié)

 

規(guī)則二:為類屬性分配存儲空間時不是按照類中定義的屬性順序,而是按如下的順序:

            1、double\long;----8bytes

            2、int\float;----4bytes

            3、char\short;----2bytes

            4、boolean\byte;----1bytes

            5、reference;----4bytes

例如:

Java代碼  

public class A {   

    byte a;   

    char b;   

    int c;   

    long d;   

    Object e;   

}   

 

 

 

屬性        需要字節(jié)數(shù)        累積字節(jié)數(shù)

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的目的是,規(guī)則一中描述每個對象按照8個字節(jié)的粒度對齊,這樣下一個分配的對象的開始位置必須在8的倍數(shù)上,而離27最近的8的倍數(shù)是32,因此加了5bytes。A占用32bytes

可以用jmap看一下這個計算是否準(zhǔn)確

 

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

例如:

Java代碼  

class B{  

    long a;  

    int b;  

    int c;  

}  

 

class BB extends B{  

    long d;  

}  

 

 屬性        占用字節(jié)數(shù)        累計字節(jié)數(shù)

header        8        8

a        8        16

b        4        20

c        4        24

d        8        32

 

這里累計字節(jié)正好是8的倍數(shù),滿足規(guī)則一,因此不用padding字節(jié)。BB對象內(nèi)存占用了32bytes

 

規(guī)則四:父類的最后一個屬性和子類第一個屬性必須按4個字節(jié)的倍數(shù)對齊

例如:

Java代碼  

class B{  

    long a;  

    int b;  

    char c;  

}  

 

class BB extends B{  

    long d;  

}  

 

 

屬性        占用的字節(jié)        累計字節(jié)

head        8        8

a        8        16

c        2        18

         padding 2        20

d        8        28

         padding 4        32

 

第一次padding2是因為屬性c分配內(nèi)存后,不滿足父類最后一個屬性和子類第一個屬性按4字節(jié)粒度對齊(18除4除不開),因此需要添加兩個字節(jié)使其可以按4字節(jié)粒度對齊。

第二次paadding4是依據(jù)規(guī)則一

 

規(guī)則五:當(dāng)子類的第一個屬性是double或long,但是父類不能按8字節(jié)粒度對齊時,子類內(nèi)存分配時的順序?qū)⒉话匆?guī)則二進(jìn)行,而是按:先int\float、char\short、boolean\byte、reference、long\double

 

例如:

Java代碼  

class A{  

    byte a;  

}  

 

class B extends A{  

    long b;  

    short c;  

    byte d;  

}  

 

 

屬性        占用字節(jié)數(shù)        累計占用字節(jié)數(shù)

head        8        8

a        1        9

         padding 3        12

c        2        14

d        1        15

         padding 1        16

b        8        24

 第一次 padding 3是根據(jù)規(guī)則四

 第二次 padding 1是因為b屬性是8個字節(jié),因此需要按8個字節(jié)粒度對齊。B占用24bytes

 

 對于數(shù)組,與普通對象不同的是在頭部,頭部多了4個字節(jié)用于存儲長度信息。因此數(shù)組的head是12bytes而不是8bytes

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多