JVM 對象大小


 

對象頭在32位系統上占用8B,64位系統上占16B。 無論是32位系統還是64位系統,對象都采用8字節對齊。Java在64位模式下開啟指針壓縮,比32位模式下,頭部會大4B(mark區域變位8B,kclass區域被壓縮),如果沒有開啟 指針壓縮,頭部會大8B(mark和kclass都是8B),換句話說, HotSpot的對齊方式為8字節對齊: (對象頭+實例數據+padding)%8 等於0 且 0<=padding<8。以下說明都是以HotSpot為基准。
 
  • 在32位系統下,存放Class指針的空間大小是4字節,MarkWord是4字節,對象頭為8字節。
  • 在64位系統下,存放Class指針的空間大小是8字節,MarkWord是8字節,對象頭為16字節。
  • 64位開啟指針壓縮的情況下,存放Class指針的空間大小是4字節,MarkWord是8字節,對象頭為12字節。
  • 數組長度4字節+數組對象頭8字節(對象引用4字節(未開啟指針壓縮的64位為8字節)+數組markword為4字節(64位未開啟指針壓縮的為8字節))+對齊4=16字節。
  • 靜態屬性不算在對象大小內。

 

 

下面來通過示例來驗證一下
pom.xml添加依賴
<dependency>
    <groupId>org.openjdk.jol</groupId>
    <artifactId>jol-core</artifactId>
    <version>0.9</version>
</dependency>

 

(1)示例

public class ObjLockTest {
    public static void main(String[] args) {
        Object o = new Object();
        System.out.println("new Object:" + ClassLayout.parseInstance(o).toPrintable());
    }
}

控制台輸出:

new Object:java.lang.Object object internals:
 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 f8 (11100101 00000001 00000000 11111000) (-134217243)
     12     4        (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
分析:
首先對象頭是包含 MarkWord類型指針這兩部分信息的;
根據64位開啟指針壓縮的情況下,存放Class指針的空間大小是4字節,MarkWord是8字節,對象頭為12字節;
根據公式:對象實例的大小 = 對象頭 + 實例數據 + 對齊填充。即 12b對象頭 + 0b實例數據 + 4b對齊填充
結論:新建Object對象,會在內存占用16個字節,其中Header占12個(markword占8個+classpointer占4個),沒有實例數據,補充對齊4個。

 

(2)示例:

public class ObjLockTest {
    public static void main(String[] args) {
        A a = new A();
        System.out.println("new A:" + ClassLayout.parseInstance(a).toPrintable());
        a.setFlag(true);
        a.setI(1);
        a.setStr("ABC");
        System.out.println("賦值 A:" + ClassLayout.parseInstance(a).toPrintable());
    }

    static class A {
        private boolean flag;
        private int i;
        private String str;

        public void setFlag(boolean flag) {
            this.flag = flag;
        }

        public void setStr(String str) {
            this.str = str;
        }

        public void setI(int i) {
            this.i = i;
        }
    }
}

控制台輸出:

new A:com.lock.ObjLockTest$A object internals:
 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)                           73 c9 00 f8 (01110011 11001001 00000000 11111000) (-134166157)
     12     4                int A.i                                       0
     16     1            boolean A.flag                                    false
     17     3                    (alignment/padding gap)                  
     20     4   java.lang.String A.str                                     null
Instance size: 24 bytes
Space losses: 3 bytes internal + 0 bytes external = 3 bytes total

賦值 A:com.lock.ObjLockTest$A object internals:
 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)                           73 c9 00 f8 (01110011 11001001 00000000 11111000) (-134166157)
     12     4                int A.i                                       1
     16     1            boolean A.flag                                    true
     17     3                    (alignment/padding gap)                  
     20     4   java.lang.String A.str                                     (object)
Instance size: 24 bytes
Space losses: 3 bytes internal + 0 bytes external = 3 bytes total
新建對象A時,中Header占12個(markword占8個+classpointer占4個),實例數據中 boolean占一個字節,會補齊三個,int占4個,String占8個,無需補充對齊。

 

 

例如:

class C{
    A a;
    B b;
}

對象的大小 = 12B對象頭 + 4B*2的實例數據 + 4B的填充 = 24B

 

class C{
    A a;
    B b;
    D d;
}

對象的大小 = 12B對象頭 + 4B*3的實例數據 + 0B的填充 = 24B

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM