前言

上一章节带着大家初探JVM的类加载机制,以及双亲委派机制,本文次要介绍了Java对象头的组成以及详解


一、一个对象如何组成的?

对象在内存中的布局蕴含:对象头Mark WordKlass Pointer

  • Mark Word :用于存储对象本身的运行时数据, 如哈希码(HashCode)、GC分代年龄、锁状态标记、线程持有的锁、偏差线程ID、偏差工夫戳等
  • Klass Pointer :对象指向它的类的元数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例
  • 实例属性 :定义类中的成员属性
  • 对齐填充 : 因为HotSpot虚拟机的主动内存管理系统要求对象的起始地址必须是8字节的整数倍,也就是对象的大小必须是8字节的整数倍

二、根本类型占用的字节和位数

根本类型字节位数
byte1 byte8 bit
char2 byte16 bit
int4 byte32 bit
short2 byte16 bit
long8 byte64 bit
double8 byte64 bit
float4 byte32 bit

三、new 一个对象占用多少字节

public class Demo1 {    public static void main(String[] args) {        LockObject lockObject = new LockObject();        System.out.println(ClassLayout.parseInstance(lockObject).toPrintable());    }    static class LockObject{        int a = 4;        long b = 1;        boolean c = false;    }}

依据下面根本类型占用的字节和位数可计算出:

在开启了指针压缩的状况下:

  • 对象头 12个字节
  • 实例数据 int  a=4 4个字节,long b=1 8个字节,boolean c=false 1个字节
  • 对齐补充 7个字节。
  • 总共32个字节

四、对象内存中offset作用


offset:绝对于类对象所占内存区域起始地位的偏移

五、对象头详解

  1. 哈希值:31位的对象标识hashCode,采纳提早加载技术。它是一个地址,用于栈对堆空间中对象的援用指向
  2. GC分代年龄(占4位):记录幸存者区对象被GC之后的年龄age,个别age为15(阈值为15的起因是因为age只有4位最大就能够将阈值设置15)
  3. 锁状态标记(占2位):记录一些加锁的信息
偏差锁标识位锁标记位锁状态存储内容
001未锁定hash code(31),年龄(4)
101偏差锁线程ID(54),工夫戳(2),年龄(4)
00轻量级锁栈中锁记录的指针(64)
10重量级锁monitor的指针(64)
11GC标记空,不须要记录信息

总结

本文次要介绍了Java对象头的组成以及详解