上一篇 <<<并发编程-Lock锁
下一篇 >>>并发编程-AQS同步器
对象整体图示
1.虚拟机Mark Word图示
a、32位虚拟机图示
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)
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());
}
演示效果
new对象至少占用了多少字节
占用字节数=对象头+实例数据+对齐填充的总数,且必须是8的倍数
如果是32位的操作系统,对象头占8个字节
如果是64位的操作系统,未压缩对象头占16个字节,压缩对象头占12个字节。
tips:
1、对象头的使用情况请参考并发编程-锁的优化
2、对象的初始化情况请参考JVM基础-对象初始化
相关文章链接:
<<<Java基础-反射机制
<<<Java基础-字节码技术
<<<Java基础-创建对象的方式汇总
<<<Java基础-对象的引用类型
<<<Class文件分析一个类为啥最多支持65535个接口
<<<为什么重写equals还要重写hashcode方法
<<<如何自定义注解
<<<十大经典排序算法汇总-动画演示
<<<JDK8十大新特性
网友评论