1
、拿到内存创建指令
当虚拟机遇到内存创建的指令的时候(
new
类名),来到了方法区,找 根据
new
的参数在常量池中定位
一个类的符号引用。
2
、 检查符号引用
检查该符号引用有没有被加载、解析和初始化过,如果没有则执行类加载过程,否则直接准备为新的对象分配内存
3
、分配内存
虚拟机为对象分配内存(堆)分配内存分为指针碰撞和空闲列表两种方式;分配内存还要要保证并发安全,有两种方式。
(1
)
指针碰撞
所有的存储空间分为两部分,一部分是空闲,一部分是占用,需要分配空间的时候,只需要计算指针移动的长度即可。
(2
)
空闲列表
虚拟机维护了一个空闲列表,需要分配空间的时候去查该空闲列表进行分配并对空闲列表做更新。可以看出,内存分配方式是由
java
堆是否规整决定的,
java
堆的规整
(3
)
安全性问题的思考
假如分配内存策略是指针碰撞,如果在高并发情况下,多个对象需要分配内存,如果不做处理,肯定会出现线程安全问题,导致一些对象分配不到空间等。
解决方案:a.
线程同步策略 :
每个线程都进行同步,防止出现线程安全。
b
.
本地线程分配缓冲:也称TLAB
(
Thread LocalAllocationBuffer
),在堆中为每一个线程分配一小块独立的内存,这样以来就不存并发问题了,Java
层面与之对应的是 ThreadLocal 类的实现
4
、初始化
1.
分配完内存后要对对象的头(
Object Header
)进行初始化,这新信息包括:该对象对应类的元数据、该对象的GC
代、对象的哈希码。
2.
抽象数据类型默认初始化为
null
,基本数据类型为
0
,布尔为
false....
5
、 调用对象的初始化方法
就是执行构造方法。