JVM-HotSpot虚拟机对象探秘

目录

一、对象的实例化

(一)创建对象的方式

(二)创建对象的步骤

二、对象的内存布局

(一)对象头

(二)实例数据

(三)对齐填充

三、 对象的访问定位

(一)使用句柄

(二)直接指针

(三)对比


一、对象的实例化

(一)创建对象的方式

  1. new
  2. Class的newInstance
  3. Constructor的newInstance
  4. 使用clone
  5. 使用反序列化
  6. 第三方库Objenesis

(二)创建对象的步骤

1、判断对象对应的类是否加载、链接、初始化

当虚拟机遇到一条字节码new指令时。首先去检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类是否被加载解析初始化过。如果没有,在双亲委派模式下,使用当前类加载器以ClassLoader+包名+类名为key值进行查找对应的.class文件,如果没有找到文件,则抛出ClassNotFoundException异常

2、为对象分配内存

首先计算对象占用空间的大小,接着在堆中划分一块内存给新对象,如果实例成员变量是引用变量,仅分配引用变量空间即可,即4个字节大小

如果Java堆内存中不规则,虚拟机就必须维护一个列表,记录哪些内存可用,哪些不可用。分配的时候在列表中找一个足够大的空间分配,然后更新列表。这种分配方式叫空闲列表(Free List)。

选择哪种由Java堆是否规整决定,Java堆是否规整由所采用的的垃圾收集器是否带有空间压缩整理(Compact)的能力决定

  • 当使用Serial,ParNew等带有压缩整理过程的收集器,指针碰撞简单高效;
  • 当使用CMS基于清除(Sweep)算法收集器时,只能采用空闲列表来分配内存;(CMS为了能在多数情况下分配内存更快,设计了一个Linear Allocatioin Buffer的分配缓冲区,通过空闲列表拿到一大块分配缓冲区后,在它里面仍可使用指针碰撞方式分配)

假设Java 堆中内存时绝对规整的,所有被使用过的内存放在一边,空闲的内存放在另一边,中间放一个指针作为分界点指示器。那么内存分配就是指针指向空闲的方向,挪动一段与对象大小相等的举例。这种分配方式成为指针碰撞(Bump The Pointer)。

3、处理并发安全问题

对象创建是非常频繁的行为,还需要考虑并发情况下,仅仅修改一个指针所指向的位置也是不安全的,例如正在给对象A分配内存,指针还未修改,对象B又使用原来的指针分配内存。解决问题有两种可选方案:

  • a、对分配内存空间的动作进行同步处理。实际上虚拟机采取CAS配上失败重试的方式保证更新操作的原子性。
  • b、把内存分配的动作按照线程划分到不同的空间中进行,每个线程在Java堆中,预先分配一小块内存,称为本地线程分配缓冲(Thread Local Allocation Buffer,TLAB),只有本地缓冲区用完了,分配新的缓存区时才需要同步锁定。

虚拟机是否使用TLAB,可以通过-XX: +/-UseTLAB参数来设定。

4、初始化分配到的空间

内存分配完成后,虚拟机将分配到的内存空间(不包括对象头)都初始化为零值。如果使用了TLAB,这个工作可以提前到TLAB分配时进行。

这步操作保证对象的实例字段在Java代码中,可以不赋初始值就直接使用,程序可以访问到字段对应数据类型所对应的零值。

5、设置对象的对象头

接下来Java虚拟机还要对对象进行必要的设置,例如对象时哪个类的实例、如何才能找到类的元数据信息,对象的哈希码(实际上对象的HashCode会延后真正调用Object::hashCode()方法时才计算)、对象的GC分代年龄等信息。这些信息存放到对象的对象头(Object Header)

6、执行init方法进行初始化

上面工作完成后,从虚拟机角度来说,一个新的对象已经产生了,但是从Java程序的视角来说,对象创建才刚刚开始,对象的构造方法(Class文件中init()方法)还未执行,所有字段都是默认的零值。new指令之后接着执行init方法,按照程序员的意愿对对象进行初始化,这样一个真正可用的对象才算完全构造出来

二、对象的内存布局

(一)对象头

对象头包括两部分,第一类是存储对象自身运行时的数据Mark Word,第二类是类型指针

这部分数据的长度在32位和64位的虚拟机(未开启指针压缩中)分别是32bit和64bit,官方称为【Mark Word】运行时元数据,其包括:

  • 哈希值
  • GC分代年龄
  • 锁状态标志
  • 线程持有的锁
  • 偏向线程ID
  • 偏向时间戳

对象头里的信息是与对象自身定义的数据无关的额外存储成本,考虑到虚拟机的空间效率,根据对象状态的不同,Markword可以复用自己的空间。

类型指针

即对象指向它的类型元数据的指针,Java虚拟机通过这个指针来确认该对象属于哪个类的实例

说明:如果对象是一个Java数组,那在对象头中还必须有一块用于记录数组长度的数据,因为虚拟机可以通过普通Java对象的元数据信息确定Java对象的大小,但是如果数组的长度是不确定的,将无法通过元数据中的信息推断出数组的大小。

(二)实例数据

对象的实例数据部分,是对象的真正存储的有效信息,即我们在程序代码中定义的各种类型的字段内容,无论是父类继承下来,还是子类中定义的字段都要记录下来。

1、这部分的存储顺序会受到虚拟机分配策略参数和字段在Java源码中定义顺序的影响。
2、分配策略参数-XX:FieldsAllocationStyle
3、HotSpot虚拟机默认的分配顺序为longs/doubles、ints、shorts/chars、bytes/booleans、oops(Ordinary Object Pointers)
4、从默认的分配策略中可以看出,相同宽度的字段总被分配到一起存放。
5、在满足这个前提条件的情况下,在父类中定义的变量会出现在子类之前。
6、如果HotSpot虚拟机的+XX:CompactFields参数值为true(默认也是true),那么子类中较窄的变量也允许插入父类变量的空隙之间,以节省一点点空间。

(三)对齐填充

对齐填充,这并不是必然存在,没有特别的意义,它仅仅起着占位符的作用。

因为HotSpot虚拟机自动内存管理系统,要求对象的起始地址必须是8字节的整数倍,换句话就是任何对象的大小都必须是8字节的整数倍。

对象头已经精心设计为8字节的整数倍,1倍或者2倍。对象实例数据部分如果没有对齐的话,就需要通过对其填充来补全。

三、 对象的访问定位

(一)使用句柄

使用句柄,Java堆中将划出一块内存作为句柄池,reference中存储的就是对象的句柄地址,句柄包含对象实例数据与类型数据各自的具体信息。

(二)直接指针

使用指针,reference中存储的直接就是对象地址,如果访问对象本身,不需要多一次的间接访问的开销。

(三)对比

两种方式各有优势:

  • 使用句柄最大好处是reference中存放的是稳定句柄地址,在对象被移动(垃圾搜集时会产生)时只改变句柄中实例数据指针,reference本身不用改变。
  • 使用指针最大好处就是速度快,节省了一次指针定位的时间开销,由于对象访问在Java中非常频繁,所以积少成多也是一项可观的执行成本。
  • HotSpot主要是用指针,进行对象访问(例外情况,如果使用Shenandoah收集器的话,也会有一次额外的转发)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/156033.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

小迈迈驰组态软件支持国产龙芯2K1000等处理器

自2019年起,南京迈思德电气自动化有限公司组织研发团队,进行跨平台组态软件的研发,适配国产处理器,目前已经完成单机版产品的研发,并在基于龙芯2K1000处理器[Loongnix操作系统]的加固人机界面产品上应用。 Loongnix是龙…

可逆矩阵的性质

如果矩阵A可逆,那么它的逆矩阵也可逆,并且如果矩阵A可逆,假设是一个不为0的数,那么也可逆,并且如果矩阵A和都可逆,而且它们的阶数也相同,那么它们的乘积也是可逆的,并且如果矩阵A可逆…

docker数据卷详细讲解及数据卷常用命令

docker数据卷详细讲解及数据卷常用命令 Docker 数据卷是一种将宿主机的目录或文件直接映射到容器中的特殊目录,用于实现数据的持久化和共享。Docker 数据卷有以下特点: 数据卷可以在一个或多个容器之间共享和重用,不受容器的生命周期影响。…

<Linux>(极简关键、省时省力)《Linux操作系统原理分析之Linux 进程管理 2》(6)

《Linux操作系统原理分析之Linux 进程管理 2》(6) 4 Linux 进程管理4.2 Linux 进程的状态和标识4.2.1 Linux 进程的状态及转换4.2.2 Linux 进程的标识4.2.3 进程标识哈希表 4 Linux 进程管理 4.2 Linux 进程的状态和标识 4.2.1 Linux 进程的状态及转换…

提高Producer的发送速度

发送一条消息出去要经过三步,一是客户端发送请求到服务器,二是服务器处理该请求,三是服务器向客户端返回应答,一次消息的发送耗时是上述三个步骤的总和。在一些对速度要求高,但是可靠性要求不高的场景下,比…

2023年中国机动车拍卖网络化趋势加速,网络拍卖专场数量大幅上升至47489场[图]

2022年,由于机动车拍卖网络化趋势继续加速,网络拍卖专场数量大幅上升,全国机动车专场拍卖会高达59450场,较上年攀升125.31%。在389家拍卖企业中,举办场次超过100场的企业有27家,合计54850场,占比…

11.4MyBatis(基础)

一.搭环境 1.创建完SSM项目,添加MySQL和MyBatis后,项目启动一定会报错,这是正常情况. 2.配置文件 properties: server.port9090 spring.datasource.urljdbc:mysql://127.0.0.1:3306/test1?characterEncodingutf8&useSSLfalse spring.datasource.usernameroot spring.d…

快速入门:构建您的第一个 .NET Aspire 应用程序

##前言 云原生应用程序通常需要连接到各种服务,例如数据库、存储和缓存解决方案、消息传递提供商或其他 Web 服务。.NET Aspire 旨在简化这些类型服务之间的连接和配置。在本快速入门中,您将了解如何创建 .NET Aspire Starter 应用程序模板解决方案。 …

贪吃蛇、俄罗斯方块

贪吃蛇 一、创建新项目 创建一个新的项目,并命名。 创建一个名为images的文件夹用来存放游戏相关图片。 然后再在项目的src文件下创建一个com.xxx.view的包用来存放所有的图形界面类, 创建一个com.xxx.controller的包用来存放启动的入口类(控制类) 二…

通信原理板块——脉冲编码调制(PCM)

微信公众号上线,搜索公众号小灰灰的FPGA,关注可获取相关源码,定期更新有关FPGA的项目以及开源项目源码,包括但不限于各类检测芯片驱动、低速接口驱动、高速接口驱动、数据信号处理、图像处理以及AXI总线等 1、脉冲编码调制PCM原理 将模拟信号…

C++第一讲:起源和规范

面向过程和面向对象 大千世界中,事务的发展规律都是面向过程的状态。例如一颗种子从生根到发芽,从发芽到开花,从开花到结果。 但是面向过程是一个更贴近**“机械”**的表达方式,而更贴近人类思想的却是面向对象的表达方式。 以…

2023年中国冲击波治疗仪市场发展趋势分析:未来市场增长空间更大[图]

冲击波在临床医学领域最早应用于体外冲击波碎石,在二十世纪八十年代末期,体外冲击波碎石技术开始被运用到骨科及康复理疗领域,经过十余年的临床研究,冲击波疗法日益完善,应用范围也日益扩大。冲击波作为一种介于保守疗…

【MATLAB】史上最全的9种数据拟合算法全家桶

有意向获取代码,请转文末观看代码获取方式~ 大家吃一顿火锅的价格便可以拥有9种数据拟合算法,绝对不亏,知识付费是现今时代的趋势,而且都是我精心制作的教程,有问题可随时反馈~也可单独获取某一算法的代码&#xff08…

什么是等保测评?

随着近几年随着网络技术的发展,互联网应用的普及和丰富,互联网安全问题也日益严重,利用信息技术进行的高科技犯罪事件呈现增长态势。从2004年度CNCERT的信息网络安全工作报告中我们看到,信息网络安全事故在逐年上升,20…

leetcode:移除链表元素

1.题目描述 题目链接:203. 移除链表元素 - 力扣(LeetCode) 2.解题思路 我们定义一个cur指向当前结点,定义prev指向前一个结点,next指向下一个结点 如果cur->valval,那我们就删除这个结点 怎么删除呢…

PHP写一个电商 Api接口需要注意哪些?考虑哪些?

随着互联网的飞速发展,前后端分离的开发模式越来越流行。编写一个稳定、可靠和易于使用的 API 接口是现代互联网应用程序的关键。本文将介绍在使用 thinkphp6 框架开发 电商API 接口时需要注意的要点和考虑的问题,并提供详细的逻辑步骤和代码案例。 1. …

Spring Cloud Hystrix:服务容错保护

💗wei_shuo的个人主页 💫wei_shuo的学习社区 🌐Hello World ! Spring Cloud Hystrix:服务容错保护 Spring Cloud Hystrix是Spring Cloud中的一个子项目,主要用于服务容错保护;分布式系统中&…

系列一、JVM概述

一、概述 1.1、Java发展中的重大事件 1.2、虚拟机 vs Java虚拟机 1.2.1、虚拟机 1.2.2、Java虚拟机 1.2.3、Java虚拟机的作用 Java虚拟机是二进制字节码的运行环境,负责装载字节码到其内部,解释/编译为对应平台上的机器指令指令。每一条Java指令&#…

矩阵乘法的性质

矩阵乘法满足结合律和分配律,不满足交换律。 - 结合律 (AB)CA(BC) 其中为常数 - 分配律 A(BC)ABAC (AB)CACBC

MPN – 制造零件号

S/4 1610 中的 MPN – 基于 NAST 的输出管理 我试图查找有关 MPN 设置的信息,但找不到详细的配置步骤。在浏览了一些信息和 help.sap 链接后,我能够在 S/4 1610 系统中配置 MPN 设置,这与使用旧输出类型(Nast 和输出类型 NEU&…