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虚拟机通过这个指针来确定该对象是哪个类的实例