JVM中的对象内存布局
所属分类 java
浏览量 1331
创建对象的方式
new 反射机制 Object.clone 反序列化 Unsafe.allocateInstance
Unsafe.allocateInstance不会初始化实例字段
new 和反射机制 通过调用构造器来初始化实例字段
没有定义构造函数 自动添加一个无参数的构造函数(默认构造函数)
如果父类没有默认构造器,子类的构造函数需要显式地调用父类带参数的构造函数
super this
Java 对象 对象头
标记字段 类型指针
存储 Java对象的运行数据,如哈希码、GC 信息以及锁信息,类型指针则指向该对象的类。
64位JVM中,对象头标记字段占 64 位,类型指针占 64 位。 每个 Java 对象在内存中的额外开销是 16 字节。
压缩指针 将堆中64位的Java对象指针压缩成32位
内存对齐 JVM堆中对象的起始地址需要对齐至8的倍数 对象间的填充
指针里存放地址,由于堆中对象的起始地址对齐至8的倍数,所以指针存放一个引用(或者对象的类)的内存地址时,不用存放最后的三位二进制数。
因为所有对象或类的内存地址都对齐了8,内存地址的最低三位总是0,32位的指针可以寻址到 2 的 35 次方个字节,
也就是 32GB 的地址空间(超过 32GB 则会关闭压缩指针)。
Java 虚拟机要求long字段、double字段,以及非压缩指针状态下的引用字段地址为8的倍数。
CPU的缓存行机制 如果字段不对齐,有可能出现跨缓存行的字段。
该字段的读取可能需要替换两个缓存行,而该字段的存储也会同时污染两个缓存行。
伪共享
同一对象中不同的 volatile 字段,逻辑上它们并没有共享内容,因此不需要同步。
如果这两个字段恰好在同一个缓存行中,那么对这些字段的写操作会导致缓存行的写回,也就造成了实质上的共享。
Java8 引入 @Contended,用来解决对象字段之间的伪共享。
Java 虚拟机 让不同的 @Contended 字段处于独立的缓存行中, 避免无谓的缓存行同步操作。
jvm参数加上 -XX:-RestrictContended @Contended注解才会生效
上一篇
下一篇
37种融资模式
企业分析要点
linux打开文件最大数设置
判断文件是否是符号链接
maven clean package install deploy区别
jar冲突处理