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

关于对象头引发的思考,对象在内存中是如何存储的

程序员文章站 2022-07-10 20:55:59
今天在看并发编程这本书的时候,看到了对象头这一名词(如下图所示),这是我第一次接触这个概念,或是说第一次留意到这个概念,这不仅引起了我的深思,对象到底是以何种形式存储在内存中呢首先,我上网搜了一下对象在内存中的存储结构,经过筛选得到这样一张图,了解到对象的内存结构包括对象头(MarkWord,类指针,数组长度),实例数据,对齐(为了加快访问速度,java对象的大小必然是8的整数倍)三个部分。下面直接上代码,看看对象的每个部分到底是怎么样的new Object() 和 new byte[0]占多少字...

今天在看并发编程这本书的时候,看到了对象头这一名词(如下图所示),这是我第一次接触这个概念,或是说第一次留意到这个概念,这不仅引起了我的深思,对象到底是以何种形式存储在内存中呢

关于对象头引发的思考,对象在内存中是如何存储的
首先,我上网搜了一下对象在内存中的存储结构,经过筛选得到这样一张图,了解到对象的内存结构包括对象头(MarkWord,类指针,数组长度),实例数据,对齐(为了加快访问速度,java对象的大小必然是8的整数倍)三个部分。
关于对象头引发的思考,对象在内存中是如何存储的

下面直接上代码,看看对象的每个部分到底是怎么样的
new Object() 和 new byte[0]占多少字节
参考:https://blog.csdn.net/Siiiirius/article/details/107108114

使用的工具
    <dependency>
        <groupId>org.openjdk.jol</groupId>
        <artifactId>jol-core</artifactId>
        <version>0.10</version>
    </dependency>
代码
public class Test {
public static void main(String[] args) throws IOException {
    System.out.println(ClassLayout.parseInstance(new byte[0]).toPrintable());
    System.out.println("-------------------");
    System.out.println(ClassLayout.parseInstance(new Object()).toPrintable());
}
}
输出结果
32位虚拟机
[B object internals:
 OFFSET  SIZE   TYPE DESCRIPTION                               VALUE
      0     4        (object header)                           09 00 00 00 (00001001 00000000 00000000 00000000) (9)
      4     4        (object header)                           78 04 96 06 (01111000 00000100 10010110 00000110) (110494840)
      8     4        (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
     12     0   byte [B.<elements>                             N/A
     12     4        (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

-------------------
java.lang.Object object internals:
 OFFSET  SIZE   TYPE DESCRIPTION                               VALUE
      0     4        (object header)                           05 00 00 00 (00000101 00000000 00000000 00000000) (5)
      4     4        (object header)                           70 0d 96 06 (01110000 00001101 10010110 00000110) (110497136)
Instance size: 8 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total

可以看到,在32位虚拟机下,byte数组对象头总共12个字节,前4个字节存储的是mark word,接下来4个字节是指向对象所属的类的指针,也就是指向byte[].class的指针,最后4个字节保存数组的长度。

接下来是数组元素列表,由于这里是数组长度是0,所以,这里没有元素,占用0个字节,最后4个字节是对齐填充(为了加快访问速度,java对象的大小必然是8的整数倍),总共占用了16个字节。

object对像只有对象头,mark word 4个字节,class指针4个字节。总共占用8个字节。

64位虚拟机
[B 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)                           27 42 07 00 (00100111 01000010 00000111 00000000) (475687)
     12     4        (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
     16     0   byte [B.<elements>                             N/A
Instance size: 16 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total

-------------------
java.lang.Object object internals:
 OFFSET  SIZE   TYPE DESCRIPTION                               VALUE
      0     4        (object header)                           05 00 00 00 (00000101 00000000 00000000 00000000) (5)
      4     4        (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4        (object header)                           96 20 00 00 (10010110 00100000 00000000 00000000) (8342)
     12     4        (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

64位虚拟机默认开启了指针压缩,因此,class指针只占用4个字节,如果不开启指针压缩,指针将会占用8个字节。所以byte数组对象头 mark word是8个字节,class指针是4个字节,数组大小4个字节,对象头大小为16字节,因此byte数组不需要对齐,总共16字节。

object对象 mark word 8字节,class直接4个字节,填充4个字节,总共16字节。

练习:User (int id,String name) User u = new User(1,‘张三’)占用多少字节呢?

markword 8字节,开启classPointer压缩 ,classpointer 4字节,instance data int 4字节,开启普通对象指针压缩 String 4字节 padding 4 一共24字节

本文地址:https://blog.csdn.net/qq_40121580/article/details/107460696