1、当Java虚拟机遇到一条new指令时,首先会去检查这条指令的参数是否能在常量池中定位一个类的符号引用
2、判断是否进行过类加载
3、内存分配:
指针碰撞:java堆内存规整,垃圾收集器具备空间压缩整理能力(Serial、ParNew)
空闲列表:内存不规整,维护一个列表来记录哪块内存是可用的,垃圾收集器具备标记-清除(CMS)
(并发分配是否会出现问题?
会:可能出现正在给对象A分配内存,指针还没来得及修改,对象B又同时使用了原来的指针来分配内存的情况
解决:两种可选方案:一种是对分配内存空间的动作进行同步处理——实际上虚拟机是采用CAS配上失败重试的方式保证更新操作的原子性;另外一种是把内存分配的动作按照线程划分在不同的空间之中进行,即每个线程在Java堆中预先分配一小块内存,称为本地线程分配缓冲(Thread Local Allocation Buffer,TLAB),哪个线程要分配内存,就在哪个线程的本地缓冲区中分配,只有本地缓冲区用完了,分配新的缓存区时才需要同步锁定。虚拟机是否使用TLAB,可以通过-XX:+/-UseTLAB参数来设定。)
对象在堆内存中的存储布局可以划分为三个部分:对象头(Header)、实例数据(Instance Data)和对齐填充(Padding)(占位符)
对象头包含两类信息:
1、存储自身运行时数据:hashcode,GC分代年龄,锁标识等
2、类型指针,即对象指向它的类型元数据的指针,Java虚拟机通过这个指针来确定该对象是哪个类的实例
本文详细解析Java虚拟机在遇到new指令时的工作流程,包括符号引用定位、类加载检查、内存分配策略如指针碰撞与空闲列表,以及并发分配的解决方案。深入探讨对象在堆内存中的存储布局,包括对象头、实例数据和对齐填充,揭示对象运行时数据存储与类型指针的重要性。

被折叠的 条评论
为什么被折叠?



