• JAVA对象大小的获取


    1. Java 对象的内存布局

    Java的实例对象、数组对象在内存中的组成包括如下三部分:对象头Hearder、实例数据、内存填充。示意图如下所示
    在这里插入图片描述

    • 对象头
      其主要包括两部分数据:Mark Word、Class对象指针。特别地对于数组对象而言,其还包括了数组长度数据。在64位的HotSpot虚拟机下,Mark Word占8个字节,其记录了Hash Code、GC信息、锁信息等相关信息;而Class对象指针则指向该实例的Class对象,在开启指针压缩的情况下占用4个字节,否则占8个字节;如果其是一个数组对象,则还需要4个字节用于记录数组长度信息。这里列出64位HotSpot虚拟机Mark Word的具体含义,以供参考。需要注意的是在下图的Mark Word中,左侧为高字节,右侧为低字节
      在这里插入图片描述

    • 实例数据
      用于存放该对象的实例数据

    • 内存填充
      64位的HotSpot要求Java对象地址按8字节对齐,即每个对象所占内存的字节数必须是8字节的整数倍。因此Java对象需要通过内存填充来满足对齐要求

    注:

    在64位的HotSpot虚拟机下,类型指针、引用类型需要占8个字节。显然这大大增加了内存的消耗和占用。为此从JDK 1.6开始,64位的JVM支持UseCompressedOops选项。其可对OOP(Ordinary Object Pointer,普通对象指针)进行压缩,使其只占用4个字节,以达到节约内存的目的。在JDK 8下,该选项默认启用。当然也可以通过添加JVM参数来显式进行配置

    -XX:+UseCompressedOops  // 开启指针压缩
    -XX:-UseCompressedOops  // 关闭指针压缩
    
    • 1
    • 2

    2. 代码示例获取Java对象的大小

    引入maven依赖

    <dependency>
       <groupId>org.openjdk.jolgroupId>
       <artifactId>jol-coreartifactId>
       <version>0.17version>
       <scope>compilescope>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    2.1 基本类型的大小

    package com.zishi.jvm.jol.ab;
    public class A {
        boolean bo1;
        boolean bo2;
        byte b1;
        byte b2;
        char c1;
        char c2;
        double d1;
        double d2;
        float f1;
        float f2;
        int i1;
        int i2;
        long l1;
        long l2;
        short s1;
        short s2;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    public static void main(String[] args) {
    	System.out.println(ClassLayout.parseClass(A.class).toPrintable());
    }
    
    • 1
    • 2
    • 3

    关闭压缩的结果如下:

    com.zishi.jvm.jol.ab.A object internals:
    OFF  SZ      TYPE DESCRIPTION               VALUE
      0   8           (object header: mark)     N/A
      8   8           (object header: class)    N/A  -- 这里占了8个字节
     16   8    double A.d1                      N/A
     24   8    double A.d2                      N/A
     32   8      long A.l1                      N/A
     40   8      long A.l2                      N/A
     48   4     float A.f1                      N/A
     52   4     float A.f2                      N/A
     56   4       int A.i1                      N/A
     60   4       int A.i2                      N/A
     64   2      char A.c1                      N/A
     66   2      char A.c2                      N/A
     68   2     short A.s1                      N/A
     70   2     short A.s2                      N/A
     72   1   boolean A.bo1                     N/A
     73   1   boolean A.bo2                     N/A
     74   1      byte A.b1                      N/A
     75   1      byte A.b2                      N/A
     76   4           (object alignment gap)    -- 对齐了4个字节
    Instance size: 80 bytes
    Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    开启压缩的结果如下:

    com.zishi.jvm.jol.ab.A object internals:
    OFF  SZ      TYPE DESCRIPTION               VALUE
      0   8           (object header: mark)     N/A
      8   4           (object header: class)    N/A  -- 这里占了4个字节
     12   4     float A.f1                      N/A
     16   8    double A.d1                      N/A
     24   8    double A.d2                      N/A
     32   8      long A.l1                      N/A
     40   8      long A.l2                      N/A
     48   4     float A.f2                      N/A
     52   4       int A.i1                      N/A
     56   4       int A.i2                      N/A
     60   2      char A.c1                      N/A
     62   2      char A.c2                      N/A
     64   2     short A.s1                      N/A
     66   2     short A.s2                      N/A
     68   1   boolean A.bo1                     N/A
     69   1   boolean A.bo2                     N/A
     70   1      byte A.b1                      N/A
     71   1      byte A.b2                      N/A
    Instance size: 72 bytes
    Space losses: 0 bytes internal + 0 bytes external = 0 bytes total
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    注:以下代码均开启压缩

    2.2 包装类型的大小

    public class B {
        Boolean bo1;
        Byte b1;
        Character c1;
        Double d1;
        Float f1;
        Integer i1;
        Long l1;
        Short s1;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    结果如下:

    com.zishi.jvm.jol.ab.B object internals:
    OFF  SZ                  TYPE DESCRIPTION               VALUE
      0   8                       (object header: mark)     N/A
      8   4                       (object header: class)    N/A
     12   4     java.lang.Boolean B.bo1                     N/A
     16   4        java.lang.Byte B.b1                      N/A
     20   4   java.lang.Character B.c1                      N/A
     24   4      java.lang.Double B.d1                      N/A
     28   4       java.lang.Float B.f1                      N/A
     32   4     java.lang.Integer B.i1                      N/A
     36   4        java.lang.Long B.l1                      N/A
     40   4       java.lang.Short B.s1                      N/A
     44   4                       (object alignment gap)    
    Instance size: 48 bytes
    Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    3.3 数组对象的大小(int[] 为例说明)

        public static void main(String[] args) {
            int[] array = new int[3];
            array[0] = 11;
            array[1] = 22;
            array[2] = 33;
            System.out.println( ClassLayout.parseInstance(array).toPrintable() );
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    结果如下:

    [I object internals:
    OFF  SZ   TYPE DESCRIPTION               VALUE
      0   8        (object header: mark)     0x0000000000000001 (non-biasable; age: 0) --对象头
      8   4        (object header: class)    0x00000c10 -- 对象字节头信息
     12   4        (array length)            3  --数组的长度
     16  12    int [I.<elements>             N/A -- 数组元素占的空间
     28   4        (object alignment gap)    -- 对齐
    Instance size: 32 bytes
    Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    数组的对象头里面包含了数组的长度,占4个字节。

    3.3 继承

    public class GrandFather {
    
        private int age;
    
        protected double money;
    
        public double bbb;
    }
    public class Son extends Father {
        private double rrr;
    }
    public class Father extends GrandFather {
    
        protected double money;
        protected double ddd;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    main方法:

    public static void main(String[] args) {
    
        System.out.println(ClassLayout.parseClass(GrandFather.class).toPrintable());
        System.out.println("-----------------------------------------------------------------");
        System.out.println(ClassLayout.parseClass(Father.class).toPrintable());
        System.out.println("-----------------------------------------------------------------");
        System.out.println(ClassLayout.parseClass(Son.class).toPrintable());
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    com.zishi.jvm.jol.ab.GrandFather object internals:
    OFF  SZ     TYPE DESCRIPTION               VALUE
      0   8          (object header: mark)     N/A
      8   4          (object header: class)    N/A
     12   4      int GrandFather.age           N/A
     16   8   double GrandFather.money         N/A
     24   8   double GrandFather.bbb           N/A
    Instance size: 32 bytes
    Space losses: 0 bytes internal + 0 bytes external = 0 bytes total
    
    -----------------------------------------------------------------
    com.zishi.jvm.jol.ab.Father object internals:
    OFF  SZ     TYPE DESCRIPTION               VALUE
      0   8          (object header: mark)     N/A
      8   4          (object header: class)    N/A
     12   4      int GrandFather.age           N/A
     16   8   double GrandFather.money         N/A
     24   8   double GrandFather.bbb           N/A
     32   8   double Father.money              N/A
     40   8   double Father.ddd                N/A
    Instance size: 48 bytes
    Space losses: 0 bytes internal + 0 bytes external = 0 bytes total
    
    -----------------------------------------------------------------
    com.zishi.jvm.jol.ab.Son object internals:
    OFF  SZ     TYPE DESCRIPTION               VALUE
      0   8          (object header: mark)     N/A
      8   4          (object header: class)    N/A
     12   4      int GrandFather.age           N/A
     16   8   double GrandFather.money         N/A
     24   8   double GrandFather.bbb           N/A
     32   8   double Father.money              N/A
     40   8   double Father.ddd                N/A
     48   8   double Son.rrr                   N/A
    Instance size: 56 bytes
    Space losses: 0 bytes internal + 0 bytes external = 0 bytes total
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    3.4 异常

        public static void main(String[] args) {
            System.out.println(ClassLayout.parseClass(Throwable.class).toPrintable());
        }
    
    • 1
    • 2
    • 3

    结果如下:

    java.lang.Throwable object internals:
    OFF  SZ                            TYPE DESCRIPTION                      VALUE
      0   8                                 (object header: mark)            N/A
      8   4                                 (object header: class)           N/A
     12   4                java.lang.Object Throwable.backtrace              N/A
     16   4                java.lang.String Throwable.detailMessage          N/A
     20   4             java.lang.Throwable Throwable.cause                  N/A
     24   4   java.lang.StackTraceElement[] Throwable.stackTrace             N/A
     28   4                  java.util.List Throwable.suppressedExceptions   N/A
     32   4                             int Throwable.depth                  N/A
     36   4                                 (object alignment gap)           
    Instance size: 40 bytes
    Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    3.5 Class

    public static void main(String[] args) {
    	System.out.println(ClassLayout.parseClass(Class.class).toPrintable());
    }
    
    • 1
    • 2
    • 3

    结果如下:

    java.lang.Class object internals:
    OFF  SZ                                              TYPE DESCRIPTION                    VALUE
      0   8                                                   (object header: mark)          N/A
      8   4                                                   (object header: class)         N/A
     12   4                     java.lang.reflect.Constructor Class.cachedConstructor        N/A
     16   4                                   java.lang.Class Class.newInstanceCallerCache   N/A
     20   4                                  java.lang.String Class.name                     N/A
     24   4                                  java.lang.Module Class.module                   N/A
     28   4                                                   (alignment/padding gap)        
     32   4                                  java.lang.String Class.packageName              N/A
     36   4                                   java.lang.Class Class.componentType            N/A
     40   4                       java.lang.ref.SoftReference Class.reflectionData           N/A
     44   4   sun.reflect.generics.repository.ClassRepository Class.genericInfo              N/A
     48   4                                java.lang.Object[] Class.enumConstants            N/A
     52   4                                     java.util.Map Class.enumConstantDirectory    N/A
     56   4                    java.lang.Class.AnnotationData Class.annotationData           N/A
     60   4             sun.reflect.annotation.AnnotationType Class.annotationType           N/A
     64   4                java.lang.ClassValue.ClassValueMap Class.classValueMap            N/A
     68  28                                                   (alignment/padding gap)        
     96   4                                               int Class.classRedefinedCount      N/A
    100   4                                                   (object alignment gap)         
    Instance size: 104 bytes
    Space losses: 32 bytes internal + 4 bytes external = 36 bytes total
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    3.6 注解

  • 相关阅读:
    CMT2300A超低功耗127-1020MHz Sub-1GHz全频段SUB-1G 射频收发芯片
    【排序算法】排序算法总结
    SpringMVC框架中的拦截器
    【react】使用useEffect操作dom
    ESP8266-Arduino编程实例-L3G4200D三轴陀螺仪驱动
    474922-26-4,DSPE-PEG-NH2,DSPE-PEG-amine,磷脂-聚乙二醇-氨基饱和18C磷脂
    900年历史的万安桥失火!传统古建筑又该如何保护?
    Java基于 SpringBoot+Vue 的游戏分享网站
    探索SPI:深入理解原理、源码与应用场景
    从概念到现实:ChatGPT 和 Midjourney 的设计之旅
  • 原文地址:https://blog.csdn.net/guo20082200/article/details/134243929