深入理解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.对象属性赋 ...
随机推荐
- 反射调用异常InvocationTargetException和代理类抛出异常
反射调用方法,如果方法抛出异常,会被包装成InvocationTargetException. 如果反射对象被代理了,在代理类中抛出异常,不会被包装成InvocationTargetException ...
- Salt States概览
作者言 我也只是SaltStack的初学者,如果文中有错误的地方,请不吝赐教. 在学习的过程,我也做了不少实验,犯了不少错,积累了一些经验,对SaltStack的运行也有一定了解,如果有什么问题,或是 ...
- android细节之android.intent.category.DEFAULT的使用
我们知道,实现android的Activity之间相互跳转需要用到Intent, Intent又分为显式Intent和隐式Intent, 显式Intent很简单,比如我在FirstActivity中想 ...
- 端口镜像——配置原理篇
镜像是指将经过指定端口(镜像端口)或者指定VLAN(镜像VLAN)的报文复制一份到另一个指定端口(观察端口),然后转发到网络监控设备,供网络管理员进行网络监控与故障管理. 看官们可以通过下面的这张图了 ...
- odoo开发笔记 -- odoo快速开发技巧
1. 需求分析到位 2. 系统对接,角色用例,数据串接 ---确定,轻易不可变更 3. 业务流程拆分细化 出图--开发人员理解的地步 4. 数据模型建立 --对应角色用例 5. 确立开发计划,划分功能 ...
- Python3基础 __file__ 查询模块的完整路径
Python : 3.7.3 OS : Ubuntu 18.04.2 LTS IDE : pycharm-community-2019.1.3 ...
- 【转】WPF DataGridComboBoxColumn使用
若要填充下拉列表,请首先使用下列选项之一设置 ComboBox 的 ItemsSource 属性.静态资源. x:Static 代码实体.ComboBoxItem 类型的内联集合.实现效果如下: 如需 ...
- python初级(302) 6 对象(三)
一.复习 1.什么是魔法方法? 2.什么是类的初始化函数? 二.什么是self 使用一个类可以创建多个对象实例,例如: ball1 = Ball("red", "smal ...
- MySQL高效分页-mybatis插件PageHelper改进
MySQL分页在表比较大的时候,分页就会出现性能问题,MySQL的分页逻辑如下:比如select * from user limit 100000,10 它是先执行select * from user ...
- 史上最全的中高级Java面试题汇总
原文链接:https://blog.csdn.net/shengqianfeng/article/details/102572691 memcache的分布式原理 memcached 虽然称为 “ 分 ...