Java基础-对象布局

上一篇 <<<并发编程-Lock锁
下一篇 >>>并发编程-AQS同步器


对象整体图示

Java基础-对象布局_第1张图片

Java基础-对象布局_第2张图片

1.虚拟机Mark Word图示

a、32位虚拟机图示

Java基础-对象布局_第3张图片

b、64位虚拟机图示

[markOop.hpp文件]
enum {  locked_value             = 0, // 0 00 轻量级锁
         unlocked_value           = 1,// 0 01 无锁
         monitor_value            = 2,// 0 10 重量级锁
         marked_value             = 3,// 0 11 gc标志
         biased_lock_pattern      = 5 // 1 01 偏向锁
  };

c、虚拟机设置说明(markOop.hpp)

Java基础-对象布局_第4张图片

2.类型指针Klass Pointer

该指针指向它的类元数据,jvm通过这个指针确定对象是哪个类的实例。
该指针的位长度为JVM的一个字大小,即32位的JVM为32位,64位的JVM为64位。
如果应用的对象过多,使用64位的指针将浪费大量内存,统计而言,64的JVM将会比32位的JVM多耗费50的内存。为了节约内存可以使用选项 -XX:+UseCompressedOops 开启指针压缩。
其中 oop即ordinary object pointer 普通对象指针。

-XX:+UseCompressedOops 开启指针压缩
-XX:-UseCompressedOops 不开启指针压缩
对象头:Mark Word+Klass Pointer类型指针 未开启压缩的情况下
32位 Mark Word =4bytes ,类型指针 4bytes ,对象头=8bytes =64bits
64位 Mark Word =8bytes ,类型指针 8bytes ,对象头=16bytes=128bits;
注意:默认情况下,开启了指针压缩 可能只有12字节。

3.实例属性

int 32bit 4byte
short 16bit 2byte
long 64bit 8byte
byte 8bit
char 16bit
float 32bit
double 64bit
boolean 1bit

4.对齐填充

对齐填充并不是必然存在的,也没有特定的含义,仅仅起着占位符的作用。
由于HotSpot虚拟机的自动内存管理系统要求对象的起始地址必须是8字节的整数倍,也就是对象的大小必须是8字节的整数倍。
而对象头部分正好是8字节的倍数(1倍或者2倍),因此,当对象实例数据部分没有对齐的时候,就需要通过对齐填充来补全。

演示效果

public static void main(String[] args) {
        Test002 lock = new Test002();
        // 底层存的是16进制
        System.out.println(Integer.toHexString(lock.hashCode()));
        System.out.println(ClassLayout.parseInstance(lock).toPrintable());
    }
Java基础-对象布局_第5张图片
演示效果

new对象至少占用了多少字节

占用字节数=对象头+实例数据+对齐填充的总数,且必须是8的倍数
如果是32位的操作系统,对象头占8个字节
如果是64位的操作系统,未压缩对象头占16个字节,压缩对象头占12个字节。

tips:
1、对象头的使用情况请参考并发编程-锁的优化
2、对象的初始化情况请参考JVM基础-对象初始化


相关文章链接:
<< << << << << <<<为什么重写equals还要重写hashcode方法
<<<如何自定义注解
<<<十大经典排序算法汇总-动画演示
<<

你可能感兴趣的:(Java基础-对象布局)