实例化过程详细讲讲?对象的基本结构你知道吗?TLAB堆上内存分配是怎么样的?你了解这个TLAB吗?
实例化过程详细讲讲?对象的基本结构你知道吗?TLAB堆上内存分配是怎么样的?你了解这个TLAB吗?你掌握的怎么样呢?
类的实例化过程
- 类加载
- 分配内存
- 初始化零值
- 状态设置
- 构造函数
上面对应下面具体执行过程:
- 在JVM中,对象的创建遵循如下过程: 当JVM遇到一条字节码new指令时,首先将去检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类是否已被加载、解析和初始化过。如果没有,那必须先执行相应的类加载过程。
- 在类加载检查通过后,接下来虚拟机将为新生对象分配内存。对象所需内存的大小在类加载完成后便可完全确定,为对象分配空间的任务实际上便等同于把一块确定大小的内存块从Java堆中划分出来。
- 内存分配完成之后,虚拟机必须将分配到的内存空间都初始化为零值,如果使用了TLAB(Thread Loacl Allocation Buffer)的话,这一项工作也可以提前至TLAB分配时顺便进行。这步操作保证了对象的实例字段在Java代码中可以不赋初始值就直接使用,使程序能访问到这些字段的数据类型所对应的零值。
- 接下来,虚拟机还要对对象进行必要的设置,例如这个对象是哪个类的实例、如何才能找到类的元数据信息、对象的哈希码、对象的GC分代年龄等信息。这些信息存放在对象的对象头之中。根据虚拟机当前运行状态的不同,如是否启用偏向锁等,对象头会有不同的设置方式。
- 在上面工作都完成之后,从虚拟机的视角来看,一个新的对象已经产生了。但是从Java程序的视角看来,对象创建才刚刚开始——构造函数,即Class文件中的
<init>()
方法还没有执行,所有的字段都为默认的零值,对象需要的其他资源和状态信息也还没有按照预定的意图构造好。 一般来说,new指令之后会接着执行<init>()
方法,按照程序员的意愿对对象进行初始化,这样一个真正可用的对象才算完全被构造出来。
注意:知识补充扩展
- 内存分配的过程中有俩种算法,一种是双指针,一种是链表法
- 内存分配的过程中会使用到TLAB过程,使用的主要目的其实就是为了解决多线程并发申请内存,使用内存的问题,JVM自有的一套解决方案。
Java对象的内存布局
一个Java对象在内存中包括3个部分:对象头、实例数据和对齐填充。
TLAB堆上内存分配是怎么样的?你了解这个TLAB吗?
Thread Local Allocation Buffer的注意事项
-
尽管不是所有的对象实例都能够在TLAB中成功分配内存,但JVM确实是将TLAB作为内存分配的首选
-
在程序中,开发人员可以通过选项:“-XX:UserTLAB” 设置是否开启TLAB空间
-
默认情况下,TLAB空间的内存非常小,仅占整个Eden空间的1%,当然我们可以通过选项“-XX:TLABWasteTarget’Percent” 设置TLAB空间所占用Eden 空间的百分比大小。
-
一旦对象在TLAB空间分配内存失败时,JVM就会尝试通过使用加锁机制确保数据的原子性,从而直接在Eden空间中分配内存。
总结:
JVM知识在面试过程中非常高频,大家一定要牢牢掌握,如果以上文章有帮助到你,希望可以点个关注,留下属于你的足迹,比心!我们下节再见哦。