天天看點

Java new一個Object()到底占用多少個位元組?

Java Object obj = new Object()到底占用多少個位元組?

Java中沒有類似C的

sizeof

的操作符,如何擷取一個對象實際占用的位元組數呢?

方法一:

有一種比較友善的方式是通過啟動jdk自帶的jvisualvm來觀察。

先寫一個測試類

public class TestObjSize {
	//定義一個直接繼承Object的類,用于觀察
	public static class TestObject {
	}

	public static void main(String[] args) {
		List<TestObject> list = new ArrayList<TestObject>(1024);
		for(int i=0;i<1000;i++) {
			//建立1000個對象,避免被回收,add到list裡面
			list.add(new TestObject());
		}
		try {
			System.in.read();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
           

編譯運作

#編譯
javac -encoding utf8 TestObjSize.java
#運作
java TestObjSize
           

jvisualvm觀察

到jdk安裝目錄bin檔案夾下找到jvisualvm.exe啟動後,檢視1000個TestObject的對象占用多少位元組:

Java new一個Object()到底占用多少個位元組?

可以看到,1000個對象占用了16000個位元組,顯然1個對象占用16個位元組。

補充

既然一個Object對象占用16個位元組,那這個16個位元組中分别存放的是什麼内容呢?

  • 前面8個位元組是對象頭,也叫markword,記錄對象被上鎖的各種狀态(鎖更新)和垃圾回收相關資訊等。
  • 接下來4個位元組(4G堆記憶體以下;或者32G以内,并且開啟了ClassPointer指針壓縮,否則是8個位元組)是一個指向對象所屬Class對象的指針。
  • 接下來4個位元組是為了8位元組對齊而填充的padding。

檢視是否開啟指針壓縮:

java -XX:+PrintFlagsFinal | find "UseCompressed"
----
bool UseCompressedClassPointers  := true  {lp64_product}
bool UseCompressedOops           := true  {lp64_product}
           

UseCompressedClassPointers:類對象指針壓縮選項。

UseCompressedOops(oops–Ordinary Object Pointers):普通對象指針壓縮選項。

方法二

使用OpenJDK提供的jol(Java Object Layout)庫進行觀察。

Maven引入依賴:

<!-- https://mvnrepository.com/artifact/org.openjdk.jol/jol-core -->
<dependency>
    <groupId>org.openjdk.jol</groupId>
    <artifactId>jol-core</artifactId>
    <version>0.10</version>
</dependency>
           

測試代碼:

Object o = new Object();
String layout = ClassLayout.parseInstance(o).toPrintable();
System.out.println(layout);
           

輸出:

OFFSET  SIZE   TYPE DESCRIPTION                               VALUE
      0     4        (object header)                           01 00 00 00 (00000001 00000000 00000000 00000000) (1)
      4     4        (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4        (object header)                           e5 01 00 20 (11100101 00000001 00000000 00100000) (536871397)
     12     4        (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
           

解釋:執行個體對象占用16個位元組。

附圖:

Java new一個Object()到底占用多少個位元組?