• 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

  • 相关阅读:
    一维数组
    do while循环(熟悉)
    while循环的概念和使用
    break关键字
    continue关键字
    for循环的概念与使用
    switchcase分支结构
    if else if else分支结构
    关于scanf()读取与返回值和回车键的问题
    WCF通过IIS寄宿服务
  • 原文地址:https://www.cnblogs.com/caoxb/p/12735570.html
Copyright © 2020-2023  润新知