【JVM学习笔记】对象的创建

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/java_faep/article/details/81358027

对象的创建

new类名—>

根据new的参数在常量池中定位一个类的符号引用—>

如果没有找到符号引用,说明类还没有被加载,则进行类的加载,解析和初始化—>

虚拟机为对象分配内存(位于堆中)—>

将分配的内存初始化为零值(不包括对象头)—>

调用对象的<init>方法

给对象分配内存

堆内存是不连续的,假设堆内存连续的,有一个类似于指针的东西,用于分割使用和未使用的内存区域,当new一个对象的时候指针向未使用的内存方法移动一部分,移动的大小(下图阴影区域)就是创建该对象所使用的内存大小,这种方式称为指针碰撞方式。

当堆内存是不连续的时候,可以采用一张表记录所有空闲的内存区域,当使用后再从表中将被使用的内存区域从表中删除,这种方式称为空闲列表的方式。

线程安全性问题

指针碰撞方式,当多个对象同时new的时候,指针的移动容易造成线程不安全,

解决方式:

1、线程同步

2、本地线程分配缓冲(TLAB)——即将内存区域划分成多个子区域,采用多个线程分别对多个子区域进行操作。(如图)

空闲列表方式也可能会造成线程不安全,也可以采用线程同步进行解决。

对象的结构

Header(对象头:对象的元数据)

           对象头主要存储的东西:

           自身运行时数据:哈希值、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳

           类型指针:对象指向类的元数据的指针,并非一定需要

InstanceData:实例数据

Padding:自动填充,字节位数不满进行填充

对象的访问定位

1、使用句柄

如果使用句柄访问方式,Java堆中会划分出一块内存来作为句柄池,reference中存储的就是对象的句柄地址,而句柄中包含了对象实例数据和类型数据各自的具体地址信息。使用句柄方式最大的好处就是reference中存储的是稳定的句柄地址,在对象被移动(垃圾收集时移动对象是非常普遍的行为)时只会改变句柄中的实例数据指针,而reference本身不需要被修改。

2、直接指针

如果使用该方式,Java堆对象的布局就必须考虑如何放置访问类型数据的相关信息,reference中直接存储的就是对象地址。使用直接指针方式最大的好处就是速度更快,他节省了一次指针定位的时间开销。

猜你喜欢

转载自blog.csdn.net/java_faep/article/details/81358027