深入理解JVM(三) -- 对象的内存布局和访问定位
一 对象的内存布局:
在HotSpot虚拟机中,对象在内存中存储的布局可以分为3块区域:对象头(Header),实例数据(Instance Data)和对齐填充(Padding)。
HotSpot的对象头包括两部分信息,一部分存储对象运转时自身信息,例如hashCode,GC分代年龄,锁状态标志,线程持有的锁,偏向线程id,偏向时间戳等,这部分数据的长度在32和64位虚拟机中分别为32和64位,官方称之为“Mark World”。对象在运行时产生的数据很多,其实早已经超出了32或64位BitMap结构能承载的限度,考虑到虚拟机的空间效率,MarkWord被设计为一个非固定的数据结构以便在极小的内存空间中尽可能多的存储信息,他会根据对象的状态复用自己的内存,例如:在32位虚拟机中,如果对象处于未被锁定的状态下时,那32bit中25bit用于存储对象的哈希码,4bit存储对象分代年龄,2bit存储锁标志位,1bit固定为0,而在其他状态(轻量级锁定,重量级锁定,GC标记,可偏向)下存储结构如下:

对象头的另一部分是类型指针,即对象指向它类元数据的指针,虚拟机通过该指针来确定这个对象是哪个类的实例,但并不是所有的虚拟机都是这样实现判断类型的。另外,如果对象是一个数组,那头对象中还需要有一块记录数组长度的数据,因为虚拟机可以通过普通对象的元数据确定对象的大小,但是从数组的元数据却无法确定数组的大小。
接下来的实例数据部分存储的是对象的有效信息,也就是在程序代码中定义的各种类型的字段内容,无论是在父类中继承下来的还是在子类中定义的,都需要记录起来,这部分的存储顺序会受到虚拟机分配策略参数和字段在代码中定义顺序的影响。HotSpot定义的策略为long/doubles,ints,shorts/chars,bytes/booleans,oops,从分配策略看出,相同宽度的字段总是被分配到一起,在满足这个前提下,父类中定义的变量会出现在子类之前。
第三部分对齐填充并不是必须存在的,也没有特殊的意义,但是由于HotSpot VM的自动内存管理系统要求对象的起始地址必须是8的整数倍,换句话说,每一个对象的大小都必须是8的整数倍,当对象所需要的内存不是8的整数倍时,才会使用对齐填充对齐来满足这一要求。
二 对象的访问定位
通过以上的步骤,一个对象就完成了内存分配和必要的初始化,那么我们如何才能定位到我们需要使用的对象呢?
Java需要通过栈上的reference数据来操作堆上的具体对象,reference类型在Java虚拟机规范中只定义了一个指向对象的引用,但并没有规定以那种方式去定位和访问堆中对象的具体位置,所以对象的访问方式也是取决于虚拟机的实现方式,目前主流的实现方式有使用句柄和直接指针两种。
句柄:
如果使用这种实现方式,那么堆中就需要划分出一片内存来作为句柄池,reference中存储的就是对象的句柄地址,而在句柄中包含了对象的实例数据与类型数据各自的地址信息,如下图:
使用直接指针进行访问,则reference中直接存储的就是对象地址,但是Java堆对象的布局中就必须考虑如何放置访问类型数据的相关信息,如下图所示:

这两种方式各有好处,使用直接指针的好处就是更快,节省了一次指针定位的时间开销,而使用句柄的方式,在对象被移动(垃圾回收)时,不需要修改reference中的地址数据,只需修改句柄池中的数据。
HotSpot当前采用的是直接指针的方式来访问对象。
深入理解JVM(三) -- 对象的内存布局和访问定位的更多相关文章
- JVM中对象的内存布局与访问定位
一.对象的内存布局 已主流的HotSpot虚拟机来说, 在HotSpot虚拟机中,对象在内存中存储的布局可以分为3块区域:对象头(Header).实例数据(Instance Data)和对齐填 ...
- 【JVM之内存与垃圾回收篇】对象实例化内存布局与访问定位
对象实例化内存布局与访问定位 从各自具体的内存分配上来讲 new 的对象放在堆中 对象所属的类型信息是放在方法区的 方法当中的局部变量放在栈空间 这 new 的对象怎么把三块粘合到一起 就是这章的内容 ...
- 关于Java的对象,锁和对象的内存布局、访问定位
1. 对象的创建和分配 创建对象(如克隆.反序列化)通常仅仅一个new关键字,但在虚拟机中,对象的创建的过程需要如下步骤: 类加载检查 先去检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并 ...
- Java对象创建的过程及对象的内存布局与访问定位
这里以HotSpot为例,且所说的对象指普通的Java对象,不包括数组和Class对象等. 1.对象创建的过程 1.类加载.解析.初始化:虚拟机遇到new时先检查此指令的参数是否能在常量池中找到类的符 ...
- JVM——深入分析对象的内存布局
概述 一个对象本身的内在结构需要一种描述方式,这个描述信息是以字节码的方法存储在方法区中的.Class本身就是一个对象,都以KB为单位,如果new Integer()为了表示一个数据就占用KB级别的内 ...
- 【JVM第六篇--对象】对象的实例化、内存布局和访问定位
写在前面的话:本文是在观看尚硅谷JVM教程后,整理的学习笔记.其观看地址如下:尚硅谷2020最新版宋红康JVM教程 一.对象的实例化 在平常写代码的过程中,我们用class关键字定义的类只是一个类的模 ...
- JVM 专题十二:运行时数据区(七)对象的实例化内存布局与访问定位
1. 对象的实例化 1.1 创建对象的方式 new 最常见的方式 变形1 : Xxx的静态方法 变形2 : XxBuilder/XxoxFactory的静态方法 Class的newInstance() ...
- JVM运行时数据区--纵向补充--对象的实例化内存布局与访问定位
对象的实例化 创建对象的方式 1.new:最常见的方式(本质是构造器) 变形1 : Xxx的静态方法 变形2 : XxBuilder/XxoxFactory的静态方法 2.Class的newInsta ...
- JVM详解(六)——对象的实例化、内存布局与访问定位
一.对象的实例化 1.创建对象的方式 2.创建对象的步骤 脑图:https://www.processon.com/view/link/61701a927d9c087040525226 3.对象属性赋 ...
随机推荐
- supervisor更改某项目配置后 需要重新启动才有效
在linux服务器上部署了node项目,使用supervisor进行管理,supervisor是个好工具,具体介绍见这里about supervisor 梗概了该项目对的某些配置后,重新启动项目,发现 ...
- fastjson WriteClassName,Double类型不打3.3D
方式一: public class SerializeConfigX extends SerializeConfig { public SerializeConfigX() { put(Double. ...
- server computer (实验室移动服务器环境)
star@xmatrix:~$ lshwWARNING: you should run this program as super-user.xmatrix ...
- 【错误解决】git报错:you are not allowed to push code to protected branches on this project
场景回忆: 本地修改需要退回到之前的版本,打算强制push本地版本覆盖远程版本,但是在git push --force后出现了以下的错误: Fix GitLab error: "you ar ...
- unity 如何打开本地文件夹,并选中文件
public static void OpenDirectory(string path, bool isFile = false) { if (string.IsNullOrEmpty(path)) ...
- IDEA中Lombok插件的安装及使用
这个插件的好处在于可以让我们的代码更简洁,减少一些重复的工作,最常用的就是@Data注解,比如在实体类上使用@Data注解,实体类的各个属性就不需要书写get和set方法. 安装方法: 1.File→ ...
- CPU时序信号和分频
- Datalogic 雕刻机
选型需要考虑: 1. 材料 2. 材质 3. 内容 4. 范围 选择镜头 5. 厚度 6. 效率 7. 效果 脚本代码: // COM 串口设置 const N_COM = "COM2&qu ...
- MQTT的Res接口发布消息
MQTT(这里采用的V2版本)发布消息的常见方法: 1.通过MQTT客户端连接MQTT服务器,建立长连接,通过接口发布消息 最常见的客户端: <dependency> <groupI ...
- npm与yarn命令
npm 1. 查看npm版本 node -v npm -v 2. 更新npm至最新版 npm install npm@latest -g 3. npm install:安装依赖 # 在本地node_m ...