###对象的创建
1、首先看方法区的常量池里有没有类加载的信息
2、分配内存:根据收集器的类型和内存的完整性来分配
如果是serial,parnew(只回收新生代)垃圾收集器,则内存空间是连续的,则用指针碰撞
如果是CMS(老年代收集器,JDK1.5以后)收集器,则内存空间不是连续的,则使用空闲列表
3、分配内存的过程中,线程是不安全的
加锁分配
在堆中为每个线程都分配一块空间,然后再同步创建
4、初始化
加载完头部数据后,为每个成员变量设置为0,这是init方法还没执行,执行new指令以后,才会执行init方法。
###对象的内存布局
1、对象头(8字节的整数倍):
对象头里包含了哈希码、GC分代年龄、锁状态标识、偏向锁(偏向线程ID),偏向时间戳
2、实例数据
3、对齐填充
并不是必然存在的。对象的大小必须是8字节的整数倍。所以需要对其。如果是8的整数倍,则不需要对其
###对象的访问定位
分为句柄访问和直接指针访问
句柄访问:
直接指针访问:
句柄访问:reference中存储了句柄的地址,如果对象位置发生变化,则只需要修改句柄指向堆中的指针即可,reference存储的句柄地址不需要动
直接指针:减少了1次指针的指向。在Java中创建对象的频繁。GC的频繁,导致多指一次消耗较大的性能。
HotSpot虚拟机选择–>直接指针