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

 

posted @ 2020-04-20 04:31  cao_xiaobo  阅读(1005)  评论(0编辑  收藏  举报