8.对象内存布局

对象内存布局

对象内存布局

​ 对象内部结构分为:对象头、实例数据、对齐填充(保证8个字节的倍数)。

1688434992516

对象头

​ 对象头分为对象标记( markOop)和类元信息(Klass0op),类元信息存储的是指向该对象类元数据(Klass)的首地址。

对象标记

​ 默认存储对象的HashCode、分代年龄和锁标志位等信息。这些信息都是与对象自身定义无关的数据,所以MarkWord被设计成一个非固定的数据结构以便在极小的空间内存存储尽量多的数据。它会根据对象的状态复用自己的存储空间,也就是说在运行期间MarkWord里存储的数据会随着锁标志位的变化而变化。

1688435326139

Hotspot 虚拟机对象头Mark Word

存储内容 标志位 状态
对象hash码、对象分代年龄 01 未锁定
指向锁记录的指针 00 轻量级锁定
指向重量级锁的指针 10 膨胀(重量级锁定)
空,不需要记录信息 11 GC标记
偏向线程ID、偏向时间戳、对象分代年龄 01 可偏向

在64位系统中,对象标记占8个字节,类型指针占了8个字节,一共是16字节

64位虚拟机存储结构

1688436544384

​ 因为GC分代年龄为4bit -》 1111 所以gc最大年龄为15

​ JOL代码演示

import org.openjdk.jol.info.ClassLayout;

public class ObjectLayoutDemo {

    public static void main(String[] args) {
        // 祖宗类
        System.out.println("################################祖宗类########################################");
        Object o = new Object();
        System.out.println(ClassLayout.parseInstance(o).toPrintable());
        // 只有类
        System.out.println("################################只有类########################################");
        Customer customer = new Customer();
        System.out.println(ClassLayout.parseInstance(customer).toPrintable());
        // 有类有属性
        System.out.println("##############################有类有属性#######################################");
        Consumer consumer = new Consumer();
        System.out.println(ClassLayout.parseInstance(consumer).toPrintable());
    }
}

class Customer {

}

class Consumer {
    int id;
    boolean flag = false;

}
################################祖宗类########################################
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

################################只有类########################################
Customer 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)                           d4 cb 00 f8 (11010100 11001011 00000000 11111000) (-134165548)
     12     4        (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

##############################有类有属性#######################################
Consumer 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)                           12 cc 00 f8 (00010010 11001100 00000000 11111000) (-134165486)
     12     4       int Consumer.id                               0
     16     1   boolean Consumer.flag                             false
     17     7           (loss due to the next object alignment)
Instance size: 24 bytes
Space losses: 0 bytes internal + 7 bytes external = 7 bytes total


#OFFSET
	偏移量,也就是到这个字段位置所占用的byte数
#SIZE
	后面类型的字节大小
#TYPE
	是Class中定义的类型
#DESCRIPTION
	DESCRIPTION是类型的描述
#VALUE
	VALUE是TYPE在内存中的值


类元信息(类型指针)

​ 类模板信息

实例数据

​ 存放类的属性(Field)数据信息,包括父类的属性信息

对齐填充

​ 虚拟机要求对象起始地址必须是8字节的整数倍。填充数据不是必须存在的,仅仅是为了字节对齐这部分内存按8字节补充对齐。

posted @ 2023-07-10 15:42  奶油炒白菜  阅读(30)  评论(0)    收藏  举报