java-基础知识-对象-对象在内存中的布局
1.用到的工具包
<!-- 用于查看当前线程锁的状态 分析JVM中Object布局 -->
<dependency>
<groupId>org.openjdk.jol</groupId>
<artifactId>jol-core</artifactId>
<version>0.7.1</version>
</dependency>
新建一个对象,放入内存中的堆。内存里的一个Java对象分为三部分:对象头,实例数据,对齐。
普通对象布局:
| markword |
| klass pointer |
| instance data |
| padding |
markword : 8Bytes 用于标记锁信息、GC信息、IdentityHashCode等
Klass Pointer 类指针 : jvm开启内存压缩(-XX:+UseCompressedClassPointer),4字节。不开启,8字节。默认开启 (Klass Pointer 不是Class Pointer 下图书写错误)
用于标记该对象是哪个Class的实例 例如:Object.class
instance data 成员变量: 大小由成员变量的类型和数量而定,如果没有成员变量,则这一块为空
补充2020-09-19
基本类型 (int,float 4字节 long,double 8字节,char,short 2字节,byte 1字节 ,boolean 实际大小1bit 占用1字节)
instance data 的总大小如果不能被4整除,那么会补齐 (alignment/padding gap)
---end---
Padding 对齐: 由上述字节而定,一个对象占用的字节数必须是8的倍数,不足的用padding对齐
补充2020-09-19
若是没有引用,则直接判断是否被8整除,不足的用padding对齐 new Person(); 未引用
若是存在引用 ,则将引用对应的4字节加上,然后判断是否被8整除,不足的用padding对齐 Person p= new Person(); 引用
---end---
例1:
Object o=new Object(); //没有成员变量 System.out.println(ClassLayout.parseInstance(o).toPrintable());

例2:
ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContextTest.xml"); Person personTest = (Person) ac.getBean("personTest");//有成员变量 System.out.println(ClassLayout.parseInstance(personTest ).toPrintable());

数组对象布局:
markword : 8Bytes 用于标记锁信息、GC信息、IdentityHashCode等
Klass Pointer 类指针 : jvm开启内存压缩(-XX:+UseCompressedClassPointer),4字节。不开启,8字节。默认开启
用于标记该对象是哪个Class的实例 例如:Object.class
数组长度: 4字节 标记数组有多少个元素
数组内容: 根据数组类型m和长度n而定,长度为m*n
如果元素为基本类型,比如byte/boolean/short/char/int/long/double,则m为对应的长度;
如果元素为数组, m是4字节的引用
如果数组长度为0,这一块为空
Padding 对齐: 由上述字节而定,一个对象占用的字节数必须是8的倍数,不足的用padding对齐
ArrayList<Integer> list=new ArrayList<>(); list.add(123); list.add(456); System.out.println(ClassLayout.parseInstance(list).toPrintable());

另外 markword 中记录了线程锁的状态


浙公网安备 33010602011771号