(2) 虚拟机内的对象

    Java是一门面向对象的语言,在Java程序运行过程中无时无刻都有对象被创建出来。

1.对象的创建

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

虚拟机为新生对象分配内存。对象所需内存在类加载过程中就可以确定,实际对象分配空间就是从Java堆中划分出一块内存。

内存分配完成后,虚拟机将分配的内存空间都初始化为零值,对象的实例变量可以不赋初值就可以直接使用就是因为虚拟机的初始化。

初始化后,虚拟家会对对象进行必要的设置,将信息存在对象的对头(Object Header)之中。

2.对象的内存布局

在HotSpot虚拟机中,对象在内存中的存储布局可以分为3块区域:对象头(Header)、实例数据(Instance Data)和对齐填充(Padding)

对象头包括两部分信息,第一部分成为“Mark Word”,用于存储对象自身的运行时数据,譬如哈希码,GC分带年龄、所状态标志等;另一部分是类型指针,即对象指向它的类元数据的指针,对象通过这个指针来确定对象是哪个类的实例。如果对象是一个数组,Header中还存有数组的长度。

实例数据部分是对象真正存储的有效信息,存储子类中定义的和父类中继承的信息。

对齐填充并不是必然存在的,起着占位符的作用。对象的数据没有对齐时,就需要通过对齐填充来补全。

3.对象的访问定位

Java程序需要通过栈上的reference数据来操作堆上的具体对象。对象访问方式取决于虚拟机实现。目前主流的访问方式有使用句柄和直接指针两种方式。

1.如果是使用句柄访问,Java堆中会划分出一块内存来作为句柄池,reference中存储的就是对象的句柄地址,句柄中包含了对象实例数据与类型数据各地的具体地址信息。

扫描二维码关注公众号,回复: 1475572 查看本文章


2.如果是使用直接指针访问,那么在java对象布局的Header里就防止访问类型数据的相关指针,而reference中存储的就是对象地址


两种方式的比较,使用句柄访问的好处是reference中存储的是句柄地址,对象被移动时只会改变句柄中的实例实例数据指针,reference本身不需要改变。直接使用指针的优点是速度快,因为节省了一次指针定位的开销。

猜你喜欢

转载自blog.csdn.net/heatsnow_/article/details/80542103