JVM学习之对象的创建

来源:互联网 发布:淘宝袜子好评语50字 编辑:程序博客网 时间:2024/06/06 14:23

1 类加载检查:虚拟机遇到一条new指令时,首先检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查这个符号引用所代表的类是否已经被加载-连接(验证、准备、解析)-初始化过。如果没有,必须先执行类的加载过程。

2 分配内存:接下来为新生对象分配内存。对象所需内存大小在类加载完成之后便可以确定。如果Java堆中内存是规整的,则使用指针碰撞的方式进行分配(用过的内存放在一边,空闲的内存放在另一边,中间有一个指针作为分界点的指示器,分配内存就是将指示器向空闲端移动一段与对象大小相等的距离);否则,使用空闲列表的方式进行分配(虚拟机维护一个列表,记录哪些内存块是可用的,分配时从中找到一块足够大的空间划分给对象实例并更新列表上的记录)。

注1: Java堆是否规整由垃圾收集器是否带有压缩整理功能所决定。如Serial、ParNew等带有Compact的收集器,分配方式为指针碰撞;而CMS这种基于Mark-Sweep算法的收集器,分配方式为空闲列表。

注2: 并发线程安全问题。两种解决方案。一种是对分配内存空间的动作进行同步处理——采用CAS加上失败重试的方式保证更新操作的原子性;另一种是使用TLAB让内存分配动作在各线程内单独进行,只有TLAB用完并分配新的TLAB时才需要同步锁定。

3 初始化零值:内存分配完成后,虚拟机将分配到的空间都初始化为零值(不包括对象头)。

注: 如果使用TLAB,该过程可以提前至TLAB分配时进行。

4 设置对象头信息:包括该对象是哪个类的实例、如何找到类的元数据信息、对象的哈希码、对象的GC分代年龄等信息。

注: 对象头信息包括两部分信息(对象头为对象内存布局三部分中的其中之一,其他为实例数据和对齐填充)。
第一部分用于存储对象自身的运行时数据,如HashCode、GC分代年龄、锁状态标志、线程持有的锁等,即Mark Word(非固定大小)。
第二部分是类型指针,即对象指向它的类元数据的指针。
如果对象为Java数组,对象头中还必须有一块用于记录数组长度的数据。

5 执行<init>方法:一般来说,执行new指令之后会接着执行<init>方法,把对象安装程序员的意愿进行初始化。至此,对象创建完成。

0 0
原创粉丝点击