深入理解java虚拟机-java对象创建(2)

java对象的创建

首先当jvm遇到一个new指令的时候,是否能在方法区查找到这个类的符号引用,并检查是否加载,如果没加载,则进行类加载,链接,初始化当前类。

假如有多个线程进行对象的创建,比如线程1,为对象A分配了一个地址X,还没来得及吧地址X赋值给A,

这个时候线程2为对象B分配地址X那么就出现线程安全问题,JVM是通过CAS保证分配的原子性,或者通过 

TLAB(Thread local allocation buffer)为线程在堆中分配私有的线程缓冲,当TLAB用完再去使用CAS分配。

开启 TLAB -XX:+UseTLAB (默认);关闭-XX:-UseTLAB

这个时候就已经在堆中分配了内存空间,初始化为零值,虚拟机还需要对这个对象的对象头进行设置,比如类元数据,hash值,GC年龄等;

补位是因为Hotspot的内存管理必须是8位的整数倍。

对象头中使用的是非固定的数据结构,即mark work

在32位的虚拟机中mark work如下,这样设计是为了在有限的空间内存储更多的数据

 

01标志位,hash码值的是当前对象的引用地址,和当前对象的存活的年纪(每monitor gc一次,年纪加1)

00标志位,当进入同步块的时候,如果没有被锁定,那么线程在当前线程栈中创建一个 lock record的空间,并且通过CAS,把对象的头中指针更改为当前lock record的指针,并且更新标志位为00

10标志位,如果上面的操作失败了,锁就要膨胀为重量级锁了锁标志的状态,指针就是重量级指针,后面的线程将阻塞

01标志位,偏向锁,实际上是和上面的一样但是还有一位0/1来区分是否可偏向

偏向位0表示不可偏向,即最上面的01标志位,偏向位1表示可以偏向,即偏向锁

 

 

对象的访问定位:

可以通过句柄池来定位对象,也可以使用直接指针(Hotspot采用这个)

通过句柄定位的优势是,当进行对象移动的时候,只需要改变句柄中实例的地址就行。

直接指针的优势是,少了一层中间句柄的开销

 

猜你喜欢

转载自blog.csdn.net/woyixinyiyi/article/details/84504195