JVM对象创建过程 (二)

**

对象的创建

**

当java虚拟机遇到一条字节码new指令时,首先检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并检查这个符号引用代表的类是否已被加载,解析和初始化过。如果没有就必须先执行相应的类的加载过程。

类加载过程通过后,虚拟机将为新生对象分配内存。对象所需内存在类加载后就完全可以确定,为对象分配空间相当于把一块确定大小的内存从Java堆中划分出来。

假设Java堆中的内存是绝对规整的,所有使用过的内存放到一边,空闲的内存放到另一边,中间放着一个指针作为分界点的指示器,分配内存相当于指针的移动。这种分配方式为**“指针碰撞”**。

如果Java堆中的内存不是规整的,使用过的内存与空闲内存交杂在一起时,无法简单的使用指针碰撞,此时,虚拟机需要维护一个列表,记录哪些内存是可用的,在分配是找到一块足够大的空间分配给对象实例,并更新表上记录。这种分配方式称为**“空闲列表”**。

选择哪种分配方式用虚拟机决定,Java堆是否规整由所采用的的垃圾收集器是否带有压缩整理的能力决定。

在并发情况下,通过指针分配内存不是安全的,如:为A分配内存,指针还未来得及修改,B有使用了原来的指针来分配内存。
解决办法:
1 对分配内存空间的动作进行同步处理,实际上虚拟机采用CSA配上失败重试的方式保证更新操作的原子性
2 把内存分配的动作按照线程分配在不同的空间中,为每个线程分配独立的内存,称为**“本地线程分配缓冲”**,即在缓冲区分配,只有本地缓冲区用完了,分配新的缓存区时才需要同步锁定。

内存分配完成后,虚拟机将分配到的内存都初始化为零值(不包括对象头),保障了对象的实例字段不赋初值也可以使用。接下来虚拟机还要对对象进行必要的设置,例如这个对象是哪个类的实例,对象的哈希码等等,这些信息会放在对象的对象头中。
new指令后要执行()方法。

符号引用:存在于虚拟机的方法区,因为对一些类和类的字段,方法的引用,在编译时不知道其具体的位置,所以会使用符号引用,在加载时再具体的解析(注意符号引用必须是能具体的找到需要引用的内容)。
CAS:CAS是Compare And Swap(比较并替换)的缩写,与锁一样实现Java的原子性操作。CAS机制当中使用了3个基本操作数:内存地址V,旧的预期值A(V的一个copy),计算后要修改的新值B。

猜你喜欢

转载自blog.csdn.net/weixin_43663421/article/details/109205636