JVM对象创建
1、类加载检查
new指令
-
首先将去检查这个指令的参数是否能在常量池中定位到这个类的符号引用
-
检查这个符号引用代表的类是否已被加载过、解析和初始化过
- 如果没有,那必须先执行相应的类加载过程
2、分配内存
对象所需的内存大小在类加载完成后便可确定,为对象分配空间的任务等同于把一块确定大小的内存从 Java 堆中划分出来
-
分配方式
-
指针碰撞
- 适用场合:堆内存规整(没有内存碎片)的情况下
- 原理:用过的内存整合到一边,没有用过的整合到一边,中间有分界指针,只要沿着没用过的方向移动位置即可
-
空闲列表
- 适用场合:堆内存不规整的情况下
- 原理:虚拟机会维护一个列表,记录那些块是可用的,分配是寻找空间,最后更新记录。
-
并发问题
- CAS+失败重试:CAS是乐观锁,每次不加锁而是假设没有冲突而去完成某项操作,如果因为冲突失败就重试,直到成功为止。
- TLAB:为每一个线程预先在 Eden 区分配一块儿内存,JVM 在给线程中的对象分配内存时,首先在 TLAB 分配,当对象大于 TLAB 中的剩余内存或 TLAB 的内存已用尽时,再采用上述的 CAS 进行内存分配
-
3、初始化零值
虚拟机需要将分配到的内存空间都初始化为零值(不包括对象头),程序能访问到这些字段的数据类型所对应的零值
4、设置对象头
这个对象是哪个类的实例、如何才能找到类的元数据信息、对象的哈希码、对象的 GC 分代年龄等信息
5、执行init方法
方法还没有执行,所有的字段都还为零。所以一般来说,执行 new 指令之后会接着执行 方法,把对象按照程序员的意愿进行初始化,这样一个真正可用的对象才算完全产生出来