JVM--对象

以HotSpot和内存区域Java堆为例,介绍HotSpot虚拟机在Java堆中对象分配、布局和访问的全过程。
1.对象的创建
1)类的加载检查
虚拟机遇到new指令,首先检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类是否已被加载、解析和初始化过。如果没有,那必须先执行相应的类的加载过程。
2)虚拟机为新生对象分配内存
对象所需内存大小在类加载完的时候就完全确定。内存分配有两种方式,当Java堆中的内存是绝对规整的,通过“指针碰撞”的方式分配,当Java堆中的内存不规整时,采用空闲列表的方式分配,列表上记录哪些内存块是空闲可用的。分配内存的同步问题有两种解决方案,一种是对分配内存的动作进行同步,另一种是通过本地线程分配缓冲,把内存分配动作按线程划分在不同的空间中进行。
3)初始化
虚拟机将需要分配的内存空间初始化为零值。
4)对象设置
虚拟机对对象进行必要的设置,例如这个对象是哪个类的实例、如何才能找到类的元数据信息、对象的哈希码、对象的GC分代年龄等信息。这些信息存放在对象的对象头之中。
5)
在上面的工作都完成之后,从虚拟机的角度看,一个新的对象已经产生了。但是从Java程序的角度看,对象的创建才刚刚开始init()方法还没有执行,所有的字段都还是零。所以,一般来说(由字节码中是否跟随invokespecial指令所决定),执行new指令之后会接着执行init()方法,把对象按照程序员的意愿进行初始化,这样一个真正可用的对象才算产生出来。访问定位:句柄或者直接指针。
2.对象的内存布局
对象的内存布局分为3个区域:对象头、实例数据、对齐填充
其中对象头包括两部分,第一部分用于存储对象自身的运行时数据,如哈希码、GC分代年龄、线程持有的锁等;另一部分是类型指针,虚拟机通过这个指针确定对象属于哪个类的实例。
实例数据部分是对象真正存储有效信息的部分,对象中各个属性都将在此存储。
对齐填充部分没有特别含义,只是为了满足对象的大小必须是8的倍数。
3.对象的访问定位
对象的访问时通过栈上的reference数据来实现定位的,对象的访问取决于具体虚拟机,目前主流的访问方式为使用句柄直接指针两种方式。
句柄访问时,堆中会划分出一块内存作为句柄池,reference存储的是句柄地址,而句柄中包含了实例数据和对象类型两个地址信息。
在这里插入图片描述
直接指针访问时,堆中的对象需要具有指向对象类型数据的指针。
在这里插入图片描述
两种方法各有优势,句柄访问的优势是,不管对象怎样被移动,reference中保存的句柄地址是稳定的。直接指针访问的优势是,它比句柄访问少一次指针定位,由于对象访问在Java中非常频繁,这个时间开销积少成多也是非常可观的优势。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值