Java对象的虚拟机创建过程

				Java对象的虚拟机创建过程---深入理解Java虚拟机学习笔记

在创建一个对象时,在语言层面通过new这样的关键字来进行创建,而虚拟机中的对象的底层创建过程要更为复杂和细致。

步骤一:类的加载检查
当虚拟机遇到new指令时会先去检查后面的参数是不是能在常量池中定位到一个类的符号引用,并检查这个符号引用代表的类是否已经被加载过,若没有,则要先进行类的加载。

步骤二:为新生对象分配内存空间
确保类被加载后,虚拟机会为对象从Java堆中分配内存空间,在使用不同的垃圾回收器时,只有部分回收器带有内存压缩整理功能,这决定了Java堆是否规整,进而决定了虚拟机采用哪一种划分内存空间的方法。
方法一:指针碰撞法 (Serial ParNew等带有Compact过程的回收器)
当Java堆中的内存是绝对规整的,所有用过的内存放到一边而空闲的内存放在另一边,中间是一个朝着空闲内存区域划分对象储存空间的指针。
空闲 空闲 空闲 指针 已使用内存单元 已使用内存单元 已使用内存单元 已使用内存单元

方法二:空闲列表法(CMS等基于最基础的标记清除 Mark-Sweep回收方法的回收器)
当Java堆中的内存是使用过的内存和空闲内存相混合的,也就是不规整的,虚拟机将维护一个表,在表上记录那些内存是空闲的,需要分配内存时只需要在表中找到记录,划分,再更新列表即可。
在分配内存的过程中,因为创建对象很可能是一个频繁操作的过程,所以也必须考虑到并发情况的线程安全,这里又涉及到两种处理思路:一种是对分配内存空间的动作进行同步,使用CAS和失败重试的方法;另一种则是把内存分配的动作按照不同的线程划分到不同的本地分配缓存中,只有缓存用完并分配新的缓存时才需要进行同步操作。

步骤三:设置对象头
Hotspot虚拟机中,对象在内存中可分为三个区域:对象头(header),实例数据(instance data),对齐填充(padding)。
对象头:
(1)存储对象自身的运行时数据:hashcode GC分代年龄 锁状态标志 线程持有的锁 偏向线程ID 偏向时间戳 等,被称为Mark Word 。 这部分信息的长度可能很多已经超过在32bit和64bit下的BitMap结构所能记录的长度,但是因为这部分信息和对象本身信息并没有关系,所以考虑到空间效率,这些信息被设计为不固定的数据结构以便在极小的空间下存储尽量多的信息,根据对象的状态复用自己的存储空间。
(2)类型指针:即对象指向它的类元数据的指针。虚拟机通过这个指针来确定这个对象是哪个类的实例(并不是所有虚拟机实现都保留类型指针,查找对象的元数据不一定要经过对象本身)。
如果对象是一个Java数组,那么对象头中还应该存储数组的长度。因为虚拟机可以通过普通 Java 对象的元数据信息确定 Java 对象的大小,但是从数组的元数据中无法确定数组的大小。

实例数据:对象真正存储的有效信息,也是在程序代码中所定义的各种类型的字段信息。
对齐填充:起占位符的作用,因为HotSpot VM中对象的大小必须是8字节的整数倍,对象头也是8字节的整数倍,所以当示例数据没有对齐的时候,就需要对其填充来进行对齐。
一个对象的大小:综上所述,HotSpot VM 中 一个Java对象由对象头(MarkWord +类型指针)+实例数据+对其填充组成,在32bit的虚拟机中存放类型指针的内存大小是4字节,Mark Word 内存大小是4字节,对象头就是8字节,如果是数组类型就需要再加4字节表示数组的长度。在64bit的虚拟机中,开启指针压缩,那么头部存放类型指针的内存大小还是4字节,但是MarkWord区域会变大为8字节,也就是头部为12字节。计算一个对象的大小要考虑对象内部不同属性是在4字节的基础上对齐的。

在完成类的加载检查,为新生对象分配内存空间,设置对象头这三步后,一个新的对象便产生了,但是仍然需要进一步的定义将对象中的各个字段进行初始化,才能形成一个可以使用的Java对象。

在拥有一个可以使用的对象后,使用创建的对象需要通过栈上的reference这样一个指向对象的引用来定位刚刚建立好的对象。而这个引用如何定位到对象是由虚拟机的具体实现方法来决定的,一般有两种方法:
方法一:使用句柄访问:
在Java堆中划分出一块内存来作为句柄池,reference指向对象的句柄地址,而句柄中包含对象的实例数据(堆中实例池)和类型信息的地址(方法区)。
方法二:直接指针访问:让reference指向对象实例化数据,再在对象实例数据中存放一个指向对象类型的指针,这样reference直接存储对象的地址
Java栈
本地变量表
int

reference
在这里插入图片描述
使用句柄方法的优势:在对象被移动时,如垃圾回收,只会改变句柄中的实例数据指针而reference本身并不会移动。
使用直接指针方法的优势:速度更快,减少了一次指针定位的开销。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值