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 中记录了线程锁的状态





posted @ 2020-06-06 22:55  雨后星辰zxj  阅读(577)  评论(0)    收藏  举报