java對象在內存的大小

前言

一直以來,對java對象大小的概念停留在基礎數據類型,好比byte佔1字節,int佔4字節,long佔8字節等,可是一個對象包含的內存空間確定不僅有這些。java

假設有類A和B,當new A()或者new B()後,實際佔用的java內存是多大呢?下面就對此進行詳細分析。apache

static class A{
    String s = new String();
    int i = 0;
}

static class B{
    String s;
    int i;
}

 

對象大小分析

如圖1,java對象在內存中佔用的空間分爲3類, 1. 對象頭(Header); 2. 實例數據(Instance Data); 3. 對齊填充(Padding)。而咱們常說的基礎數據類型大小主要是指第二類實例數據。數組

 

圖1jvm

對象頭

HotSpot虛擬機的對象頭包括兩部分信息:spa

markword和klass 。第一部分markword,用於存儲對象自身的運行時數據,如哈希碼(HashCode)、GC分代年齡、鎖狀態標誌、線程持有的鎖、偏向線程ID、偏向時間戳等。 另一部分是klass類型指針,即對象指向它的類元數據的指針,虛擬機經過這個指針來肯定這個對象是哪一個類的實例。線程

 

數組長度

若是對象是一個數組, 那在對象頭中還必須有一塊數據用於記錄數組長度,也就是一個int類型的對象,佔4字節。debug

 

對象頭佔用空間

1. 在32位系統下,存放Class指針的空間大小是4字節,MarkWord是4字節,對象頭爲8字節。指針

2. 在64位系統下,存放Class指針的空間大小是8字節,MarkWord是8字節,對象頭爲16字節。code

3. 在64位開啓指針壓縮的狀況下 -XX:+UseCompressedOops,存放Class指針的空間大小是4字節,MarkWord是8字節,對象頭爲12字節。對象

4. 若是對象是數組,那麼額外增長4個字節

 

實例數據

實例數據部分是對象真正存儲的有效信息,也是在程序代碼中所定義的各類類型的字段內容。不管是從父類繼承下來的,仍是在子類中定義的,都須要記錄起來。

 

對齊填充

最後一塊對齊填充空間並非必然存在的,也沒有特別的含義,它僅僅起着佔位符的做用。這是因爲HotSpot VM的自動內存管理系統要求對象起始地址必須是8字節的整數倍,換句話說,就是對象的大小必須是8字節的整數倍。

 

如何查看java對象大小

1. 基於JDK1.8

JDK1.8有一個類`jdk.nashorn.internal.ir.debug.ObjectSizeCalculator`能夠評估出對象的大小

// 直接調用靜態方法便可使用

ObjectSizeCalculator.getObjectSize(obj)

 

2. spark庫

spark庫中有一個類`org.apache.spark.util.SizeEstimator`

// 直接調用靜態方法便可使用

SizeEstimator.estimate(obj)

 

3. 基於JDK1.5的Instrumentation

// 須要編譯成jar調用,沒有前者方便

 

案例

分析完對象的組成結構後,再回頭來看那個問題

// 對象A: 對象頭12B + 內部對象s引用 4B + 內部對象i 基礎類型int 4B + 對齊 4B = 24B
// 內部對象s 對象頭12B + 2個內部的int類型8B + 內部的char[]引用 4B + 對齊0B = 24B
// 內部對象str的內部對象char數組 對象頭12B + 數組長度4B + 對齊0B = 16B
// 總: 對象A 24+ 內部對象s 24B + 內部對象s的內部對象char數組 16B =64B
class A {
  String s = new String();
  int i = 0;
}

// 對象B:對象頭12B + 內部對象s引用 4B + 內部對象i 基礎類型int 4B + 對齊 4B = 24B
// s沒有被分配堆內存空間
// 總: 對象B 24B
class B {
  String s;
  int i = 0;
}

 

總結

對象在jvm中不是徹底連續的,這是因爲GC的緣由,總會出現散亂的內存。這就致使了jvm必須爲每一個對象分配一段內存空間來存儲其引用的指針,再結合對象的其餘必須的元數據,使得對象在持有真實數據的基礎上還須要維護額外的數據。

在寫java代碼須要當心這些jvm內存陷阱。

 

參考

// stackoverflow給出的幾種計算對象大小方法

https://stackoverflow.com/questions/52353/in-java-what-is-the-best-way-to-determine-the-size-of-an-object

相關文章
相關標籤/搜索