JVM—HotSpot虚拟机对象探秘

参考资料:深入理解Java虚拟机:JVM高级特性与最佳实践(第3版)周志明

1、对象的创建

对象只是普通对象,不包括数组和Class对象

  • 类加载检查:当虚拟机遇到字节码New指令时,先检查这个指令的参数是否可以在常量池定位到一个类的符号引用,并且加载这个符号引用代表的类是否被加载、解析、验证、初始化过。

  • 内存****分配: 对象所需内存在类加载完成后就可以完全确定下来,实际上是在Java堆中划分一块定量大小的内存。

Java堆中 内存 分配有两种方式:

  1. 指针碰撞 :假设Java堆中使用过的内存在一边,未使用过的内存在一边,中间有一个指针作为分界点指示器,分配 内存 就是将这个指针向空闲区移动一段与对象大小相等的距离。Serial、ParNew带压缩整理的的收集器就是采用这种算法。

  2. 空闲列表 :如果Java堆的内存并不是完整的,而是使用过的和未使用的相互交错,那么虚拟机就会维护一个列表,记录哪些内存块可用。分配的时候在列表中找到空间足够大的一块分给列表实例,并更新列表记录。

  • **内存****空间初始化:**内存分配完成后,虚拟机需要将分配到的内存空间全都初始化零值。这步操作保证对象的实例字段在java代码中不赋值初始化也可以使用。

  • 设置对象头信息: 虚拟机还需要设置例如对象时哪个类的实例、如何找到对象元数据、对象哈希码,对象GC的年龄分代等信息。这些信息存放在对象头(Object Header)中。

  • init方法的执行: 从JVM角度来说对象已经创建完成,但是从Java程序的角度来说创建对象才刚开始。一般来说New指令执行完毕后会执行Class文件的<init>()方法。这样一个对象才完整的被创建。

2、对象的内存布局

在虚拟机里,对象的存储布局可以划分为三个部分:对象头(Header)、实例数据(Instance Data)和对齐填充(Padding)。

2.1 对象头

对象头通常包括两部分信息:

  • 1、存储对象自身运行时的数据---Mark Word
  • 2、类型指针,即对象指向它类型元数据的指针,JVM通过这个指针来确定对象属于哪个类的实例。并不是所有虚拟机都必须在对象数据上保留类型指针。

2.2 实例数据

实例数据是对象真正存储有效信息的的部分,即代码中定义的字段内容,不论是继承父类还是子类定义都需要记录。

这部分的存储会受到虚拟机分配策略参数和字段在Java源码中定义的顺序影响。

2.3 对齐填充

  • 这不是必然存在的,也没有特殊含义,仅仅起到占位符的作用。

由于HotSpot 虚拟机的自动内存管理系统要求对象起始必须是8字节的整数倍,因此对象实例数据部分没有对齐到8字节的整数倍,就需要对齐填充。

3、对象的访问定位

Java程序会通过 上的reference数据来 操作堆 上的具体对象。

Java虚拟机并没有定义这个reference通过什么方式去访问,定位堆中对象的具体位置,主流有两种方式:

3.1 通过句柄访问对象

Java堆中会划分出一块内存作为句柄池,reference中存储的就是对象的句柄地址。而句柄中包含了对象的实例数据和类型数据各自的地址信息。

3.2 直接指针访问对象

Java堆中的对象的内存布局需要考虑如何放置类型数据的相关信息,reference中存储的是对象的直接地址,直接访问对象本身就不需要多一次间接开销。

使用直接指针的方式最大好处就是速度快,节省一次指针定位的开销。对于HotSpot就采用了第二种对象访问方式。

相关推荐
吴冰_hogan2 小时前
JVM(Java虚拟机)的组成部分详解
java·开发语言·jvm
东阳马生架构10 小时前
JVM实战—1.Java代码的运行原理
jvm
ThisIsClark12 小时前
【后端面试总结】深入解析进程和线程的区别
java·jvm·面试
王佑辉13 小时前
【jvm】内存泄漏与内存溢出的区别
jvm
大G哥15 小时前
深入理解.NET内存回收机制
jvm·.net
泰勒今天不想展开15 小时前
jvm接入prometheus监控
jvm·windows·prometheus
东阳马生架构1 天前
JVM简介—3.JVM的执行子系统
jvm
程序员志哥2 天前
JVM系列(十三) -常用调优工具介绍
jvm
后台技术汇2 天前
JavaAgent技术应用和原理:JVM持久化监控
jvm