Java對象在內存中佔用的空間

本文主要結合lucene中RamUsageEstimator類來談談Java對象在內存中佔用的空間大小。java

注意這種計算方式適用於OpenJDK和Oracle JDK兩個版本,其它版本可能有所不一樣。數組

從總體來看,java對象由對象頭、實例數據、對齊填充3個部分組成,其中對齊填充是指對象頭的佔用空間與實例數據的佔用空間若是不是8的整數倍,就須要添加pad填滿直到總的佔用空間爲8的倍數。這裏暫時說的8的整數倍,由於在lucene源碼中64位的虛擬機是動態獲取的(具體緣由暫時不清楚,若是像網上和書上說的是固定8的整數倍就不必動態獲取了,盡信書不如無書有些東西沒看到源碼前最好別下定論),32位是固定的8個字節。對象引用的大小在64位jvm中若是開啓指針壓縮爲4個字節不然8個字節,在32位jvm中只佔4個字節。jvm

普通對象的對象頭大小爲對象引用的大小加上8字節,數組的對象頭等於普通對象頭的大小加上4個字節的和而且要按照8字節對齊。指針

字節數組佔用的空間=數組的對象頭+1*數組個數的和而且按照8字節對齊;對象

boolean數組的佔用空間與字節數組的佔用空間相同;遞歸

char數組的佔用空間=數組的對象頭+2*數組個數的和而且按照8字節對齊;接口

short數組的佔用空間與char數組的佔用空間相同;內存

int數組的佔用空間=數組的對象頭+4*數組個數的和而且按照8字節對齊;源碼

float數組的佔用空間與int數組的佔用空間相同;虛擬機

long數組的佔用空間=數組的對象頭+8*數組個數的和而且按照8字節對齊;

double數組的佔用空間與long數組的佔用空間相同;

對象數組與以上數組稍有不一樣,數組中記錄的是全部對象的引用地址,所以佔用空間=數組的對象頭+對象引用的大小*數組個數的和而且按照8字節對齊後再加上每一個對象自身佔用的實際空間;

如今詳細說明每一個對象的佔用空間,除了對象頭,其中的實例數據部分(不包括靜態變量)包括基本類型和引用類型(全部的數組和普通對象都是引用類型)。引用類型的指針大小在上面已經說過,指向真正對象的佔用空間就是如今討論的,實際上這就是一個遞歸,例如:

class Test{

    int a;

   byte[] b=new byte[10];

}

假設在64位jvm中指針壓縮的狀況下,Test對象佔用的空間=align(對象頭(4+8)+數據(4+4))+size(b)。注意:全部的引用類型不與本對象在一個連續的地址空間中,因此字節對齊align時不能包含引用對象的實際大小!

在lucene中爲了計算對象實際佔用空間就須要實現Accountable接口,就是由於當對象內部存在一個對象引用時就須要計算引用對象實際佔用空間!

相關文章
相關標籤/搜索