欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

一个Object对象要占用多少空间

程序员文章站 2022-04-13 11:33:21
...

java对象创建后,它的的组成部分如下:

       1.对象头
               在jvm虚拟机中每一个java对象都有一个对象头,对象头中包含标记字段以及对象指针:

                     1)标记字段用来储存hash码、gc信息以及锁信息,

                    2) 指针则指向该对象的类。

                 在64位jvm虚拟机中这两部分都是64位的,所以也就是需要128位大小(16 bytes)。
                 注意:64位虚拟机中在堆内存小于32GB的情况下,UseCompressedOops是默认开启的,该参数表示开启指针压缩,会将原来64位的指针压缩为32位。

     2.实例数据
         类中所有的实例字段数据。

    3.内存填充部分(alignment)
         该部分作用是用来保证java对象在虚拟机中占内存大小为8N bytes。

   4.数组长度
         这个是数组对象才特有的。

      下面以一个简单案例证明以上对对象头空间的描述:   先引入JOL工具, 全称为Java Object Layout,是分析JVM中对象布局的工具. 

 <dependency>
     <groupId>org.openjdk.jol</groupId>
     <artifactId>jol-core</artifactId>
    <version>0.9</version>
</dependency>

下面我们创建一个Object 对象,注意这个对象中没有任何属性. 

 public static void main(String[] args) {
        Object o=new Object();
        System.out.println(ClassLayout.parseInstance(o).toPrintable());
        // ClassLayout.parseInstance(o).toPrintable()     查看对象内部信息
        // 查看对象外部信息:包括引用的对象:GraphLayout.parseInstance(obj).toPrintable()
        //查看对象占用空间总大小:GraphLayout.parseInstance(obj).totalSize()
        System.out.println(   o );
    }

 输出结果分析: 

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

这里我们创建了一个Object对象. 它总共占16个字节大小. 因为它没有属性, 所以它没有实例数据, 内存填充部分,  它也不是数组,也没有数组长度. 

在上面的结果中,这16个字节全是用于对象头信息存储, 0-8的这前八个字节是标记字段用来储存hash码、gc信息以及锁信息的, 后八个字节表示指针,它则指向该对象的类, 上面显示只有前4个字节有数据, 因为64位虚拟机中在堆内存小于32GB的情况下,UseCompressedOops是默认开启的,该参数表示开启指针压缩,会将原来64位的指针压缩为32位. 

所以: 

     new一个空对象在32为系统中占用内存大小是8byte(对象头,在堆中)+ 4byte(对象的引用地址,在栈中)=12byte;
     new一个空对象在64为系统中占用内存大小是16byte(对象头,在堆中)+8byte(对象的引用地址,在栈中)=24byte

我的系统这里是64位,所以一个空对象要占用至少24byte. 

另外在细节上,我们还要注意对象头中存储的指针的大小:

接下来做了一个测试: 将UseCompressedOops关闭,再观察结果: 

  注意:   +UseCompressedOops   : 表示开启( 默认 )    -UseCompressedOops  :表示关闭. 

IDEA中设置: 

一个Object对象要占用多少空间

       

一个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)                           10 6c 41 0e (00010000 01101100 01000001 00001110) (239168528)
     12     4        (object header)                           01 00 00 00 (00000001 00000000 00000000 00000000) (1)
Instance size: 16 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total

可以看到多用了4个字节.