对象组成、分配、强弱引用

java对象在内存中的布局:

对象头:

对象头中包含了MarkWord和类型指针,如果是数组对象,还会存在数组长度。

mark word是8字节,klassword压缩前8字节,压缩后4字节,一般都是取压缩后,实例数据如果是对象,或是引用,就是8个字节,最后还要加上对齐,必须是8的倍数。

Markword:

主要就是三个信息:锁信息(markword的最后两位决定上的是什么锁),hashcode,GC信息。

32位的对象头内MarkWord在默认情况下存储着对象的HashCode、分代年龄、是否偏向锁、锁标记位等信息

64位JVM中对象头内MarkWord的默认信息存储着HashCode、分代年龄、是否偏向锁、锁标记位、unused

MarkWord被设计成为一个非固定的数据结构,以便可以复用方便存储更多有效的数据,它会根据对象本身的状态复用自己的存储空间,除了上述列出的MarkWord默认存储结构外,还有如下可能变化的结构:

实例数据:

实例数据是指一个聚合量所有标量的总和,也就是是指当前对象属性成员数据以及父类属性成员数据。

对齐填充:

指针压缩:

压缩的是引用类型,比如object类型,原来是8字节,压缩后变成4字节,然后数组长度也变成4字节了。··

为什么32bit的指针支持寻址32GB?

JOL对象大小计算:

面试题:在java中创建一个Object对象会占用多少内存?

对象头大小markword+klassword(8)=16bytesObject类中没有定义任何属性,不存在实例数据。

如果开启指针压缩,只会有markword+klassword/2(4)=12bytes,类元指针被压缩一半.

会出现4bytes的对齐填充,最终不管是否开启了指针压缩,大小应该为16字节。

数组对象大小计算:

实例对象大小计算:

Java对象分配过程详解:

类加载检测:

全限定名为key,查找.class文件。确保当前要分配的对象所在的类已经加载完成了。

内存分配:
栈上分配:

只有不会逃逸的对象才能在栈上分配,栈上分配的对象可以随着栈帧的销毁而自动回收,不需要GC回收。

如果一个对象在方法内部创建并且没有被外部引用,JVM 可能会选择在栈上分配该对象,以减少堆的压力。

基于逃逸分析的优化:

标量替换:

TLAB分配:

如果TLAB分配成功,初始化操作就会提前到内存分配这一步。

分配过程:

年老代分配:
新生代分配:
小结:
初始化内存:
设置对象头:
执行<init>函数:

一个对象从生到死的历程:

对象最终会出现在Eden区(TLAB分配也是在Eden区,栈上分配不算),而线程栈中会出现一个指向对象的引用,之后需要使用该对象时,直接通过引用中的直接地址或句柄访问该块内存区域中的对象数据。

对象的访问方式:

在Java中对象都是通过reference访问的,主要分为两种访问方式,一种为句柄访问,另一种则为直接指针访问。

句柄访问:

直接指针访问:

小结:

GC时的对象移动与对象晋升:

动态对象年龄判定:

空间分配担保机制:

小结:

对象引用类型:

强引用类型:

GC是不会回收强引用对象的,要想回收只能显式的将对象引用清空,obj=null。

软引用类型:

弱引用类型:

student是个强引用,而id=1(student)这个对象与zhuZiWR弱引用对象存在联系,所以在GC时,是可以通过student指针,判定出zhuZiWR弱对象属于存活对象!因此,GC时不会回收它!

虚引用类型:

相关推荐
未若君雅裁17 小时前
JVM 运行时数据区:程序计数器、堆、虚拟机栈与栈帧
java·jvm
killerbasd19 小时前
总结 6.9
jvm
IT龟苓膏20 小时前
Java 并发基础:进程、线程、线程状态、synchronized、volatile 一篇讲清
java·开发语言·jvm
周末也要写八哥20 小时前
线程的生命周期之线程睡眠
java·开发语言·jvm
瓦特what?21 小时前
位运算核心技巧与应用
java·jvm·算法
程序员二叉1 天前
【JVM】类加载全过程&双亲委派机制深度解析
java·jvm·面试
cfm_29141 天前
JVM 深度入门:Class文件结构 + 字节码指令详解
jvm
吴声子夜歌1 天前
JVM——线程池实现原理
java·jvm·线程池
Full Stack Developme1 天前
JVM的类加载机制
jvm
fengxin_rou1 天前
Java垃圾回收机制深度解析:从原理到实战
java·jvm·性能优化·gc·垃圾回收