JVM学习笔记(二)——对象之生

来源:互联网 发布:windows db2 编辑:程序博客网 时间:2024/05/27 14:11

1.对象的创建

1.1 当虚拟机遇到一条new指令时

a.判断该指令参数能否在常量池定位到一个类的符号引用;b.符号引用代表的类是否已被加载 解析和初始化过。如果没有则执行类加载。c.内存分配,对象所需的内存在类加载后就完全确定进行内存分配;    指针碰撞:java堆内存完全规整。    java堆为一块内存,中间一个指针作为分界点指示器,分配内存时将指针向空闲的内存那边挪动一段与对象大小相等的距离。    空闲列表:java堆不完全规整。    虚拟机维护一个列表,记录已使用的和空闲的内存。分配对象时在列表中找到一块足够大内存划分给对象。    Java堆是否规整有虚拟机是否带压缩功能决定。d. 对象分配的内存空间初始化为零值(不包括对象头)。若使用TLAB,此工作也可提前至TLAB分配时进行。e. 设置对象头(类的元数据信息,哈希码,GC分代年龄等信息)。f. 执行对象的 <init> 方法。 

1.2 并发情况下创建对象

a. CAS+失败重试 的方式保证更新操作的原子性。b. 将内存分配按照线程划分在不同的内存区域。    即每个线程先预分配一些内存,称为本地线程分配缓冲(TLAB)。各个线程使用各自的内存,当某个线程的内存不够使用时进行同步锁定。    通过-XX:+/-UseTLAB参数设定。

2. 对象的内存布局

2.1 基本布局

对象头 + 实例数据 + 对齐填充

2.2 对象头(运行时数据+类型指针)

运行时数据:哈希码,GC分代年龄,锁状态标志,线程持有的锁,偏向线程ID,偏时间戳等。这部分在32位和64位虚拟机中分别为32bit和64bit。类型指针:指向它的类元数据的指针。数组的对象头中还有一块记录数组长度的数据。

2.3 实例数据

对象存储的有效信息。存储顺序受分配策略和源码中的定义顺序影响。

2.4 对齐填充

并不是必然存在的,起到占位符的作用。HotSpot虚拟机要求对象起始地址必须是8字节的整数倍,换句话说对象的大小必须是8字节的整数倍。而头部分正好是8字节的倍数 (1倍或2倍),当实例数据没有对齐时,就需要通过对其填充来补全。

3. 对象定位(句柄+直接指针)

句柄

若使用句柄访问。java堆划分一块内存作为句柄池。reference 指向句柄,句柄包含指向对象类型数据和实例数据的指针。reference 存储稳定的句柄地址,对象移动时只改变实例数据指针。

直接指针

reference 存储的对象地址。通过对象找到对象类型数据。速度更快,节省了一次指针定位的时间开销。(HotSpot采用此方式)
原创粉丝点击