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收集器的话,也会有一次额外的转发)。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【go】报错整理与解决

文章目录 依赖下载失败checksum mismatch启动报错missing go.sum 依赖下载失败checksum mismatch > go get github.com/hibiken/asynqmon go: downloading github.com/hibiken/asynqmon v0.7.2 go: github.com/hibiken/asynqmonv0.7.2: verifying module: checksum mismatc…

QUIC协议详解

前言协议特点QUIC协议与HTTP/2协议区别QUIC协议的多路复用技术优势QUIC协议在Java中的应用存在的问题 前言 QUIC(Quick UDP Internet Connections)是一种基于 UDP 的传输层协议,由 Google 提出。从协议栈可以看出,QUIC HTTP/2 …

计算机毕业设计选题推荐-一周穿搭推荐微信小程序/安卓APP-项目实战

✨作者主页:IT研究室✨ 个人简介:曾从事计算机专业培训教学,擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Python…

自定义Graph Component:1.2-其它Tokenizer具体实现

本文主要介绍了Rasa中相关Tokenizer的具体实现,包括默认Tokenizer和第三方Tokenizer。前者包括JiebaTokenizer、MitieTokenizer、SpacyTokenizer和WhitespaceTokenizer,后者包括BertTokenizer和AnotherWhitespaceTokenizer。 一.JiebaTokenizer   Ji…

智慧环保:科技驱动下的环境保护新篇章

智慧环保:科技驱动下的环境保护新篇章 环境保护已经成为当今社会的重要议题,而科技的飞速发展为我们开启了智慧环保的新篇章。在这篇文章中,我们将介绍智慧环保所带来的机会和创新,以及科技在环境保护中的重要作用。 智慧环保的理…

香港科技大学广州|智能制造学域机器人与自主系统学域博士招生宣讲会—中国科学技术大学专场

🏠地点:中国科学技术大学西区学生活动中心(一楼)报告厅 【宣讲会专场1】让制造更高效、更智能、更可持续—智能制造学域 🕙时间:2023年11月16日(星期四)18:00 报名链接&#xff1a…

利用回溯绕过正则表达式

目录 利用strpos的特性拿到flag 利用回溯绕过正则表达式 利用回溯次数绕过正则表达式并且实现文件上传 使用回溯绕过正则表达式waf拿到flag 本篇会讲解三个实验来分别绕过正则表达式,python的正则表达式和Javascript的正则表达式大致相同如果有正则表达式不太懂…

stylelint报错at-rule-no-unknown

stylelint报错at-rule-no-unknown stylelint还将各种 sass -rules 标记mixin为include显示未知错误 at-rule-no-unknown ✖ stylelint --fix:Deprecation warnings: 78:1 ✖ Unexpected unknown at-rule "mixin" at-rule-no-unknown 112:3 ✖ Unexpected un…

设计模式-适配器-笔记

适配器模式Adapter 动机(Motivation) 在软件系统中,由于应用环境的变化,常常需要将“一些现存的对象”放在新的环境中应用,但是新环境要求的接口是在这些现存对象所不满足的。 如何应对这种“迁移的变化”&#xff1…

力扣第695题 岛屿的最大面积 C++ DFS BFS 附Java代码

题目 695. 岛屿的最大面积 中等 相关标签 深度优先搜索 广度优先搜索 并查集 数组 矩阵 给你一个大小为 m x n 的二进制矩阵 grid 。 岛屿 是由一些相邻的 1 (代表土地) 构成的组合,这里的「相邻」要求两个 1 必须在 水平或者竖直的四个方向上 相邻。你…

如何安装clang-9,clang,clang++

# 制定要version9的clang sudo apt-get install clang-9 # 创建软链 sudo ln -s /usr/bin/clang-9 /usr/bin/clang sudo ln -s /usr/bin/clang-9 /usr/bin/clang如果你已经安装了 clang-9,那么 clang 已经包含在内。通常,clang 是 clang 的一个符号链接&…

【Liunx】部署WEB服务:Apache

【Liunx】部署WEB服务:Apache 概述Apache1.介绍2.Apache文件路径3.Apache详解(1)安装Apache(2)启动Apache(3)配置文件a.Apache主配置文件:vim /etc/httpd/conf/httpd.conf信息:b.基于主机头的虚拟主机 (4)开始演示:a.新建两个网站根目录b.分别…

DVWA - 4

文章目录 JavaScriptlowmedium JavaScript 前端攻击。token 不能由前端生成,js 很容易被攻击者获取,从而伪造 token。同样其他重要的参数也不能由前端生成。 low 不修改输入,点击提交报错: 根据提示改成 success,还是报错&…

3.6 Windows驱动开发:内核进程汇编与反汇编

在笔者上一篇文章《内核MDL读写进程内存》简单介绍了如何通过MDL映射的方式实现进程读写操作,本章将通过如上案例实现远程进程反汇编功能,此类功能也是ARK工具中最常见的功能之一,通常此类功能的实现分为两部分,内核部分只负责读写…

4.1 Windows驱动开发:内核中进程与句柄互转

在内核开发中,经常需要进行进程和句柄之间的互相转换。进程通常由一个唯一的进程标识符(PID)来标识,而句柄是指对内核对象的引用。在Windows内核中,EProcess结构表示一个进程,而HANDLE是一个句柄。 为了实…

实时数仓-Flink使用总结

阿里云实时计算Flink版是阿里云基于Apache Flink构建的企业级、高性能实时大数据处理系统。具备一站式开发运维管理平台,支持作业开发、数据调试、运行与监控、自动调优、智能诊断等全生命周期能力。本期将对Flink的使用进行总结。 1. Flink产品回顾 阿里云实时计算…

python趣味编程-5分钟实现一个Flappy Bird游戏(含源码、步骤讲解)

Python 中的 Flappy Bird 游戏可以免费下载开源代码,它是为想要学习 Python 的初学者创建的。 该项目系统使用了 Pygame 和 Random 模块。 Pygame 是一组跨平台的 Python 模块,专为编写视频游戏而设计。 Python 中的 Flappy Bird 代码 – 项目信息 项目名称:Python 中的 Fl…

2023年中国骨质疏松治疗仪发展趋势分析:小型且智能将成为产品优化方向[图]

骨质疏松治疗仪利用磁场镇静止痛、消肿消炎的治疗作用迅速缓解患者腰背疼痛等骨质疏松临床症状。同时利用磁场的磁-电效应产生的感生电势和感生电流,改善骨的代谢和骨重建,通过抑制破骨细胞、促进成骨细胞的活性来阻止骨量丢失、提高骨密度。 骨质疏松治…

2023-2024 年适用于 Windows 电脑的顶级视频录制软件

想捕捉您正在在线观看的视频吗?使用网络摄像头录制视频会议以供日后参考。正在寻找可以完成这些任务的视频捕捉软件?这篇文章说明了一切。以下是一些适用于 Windows PC 的最佳视频录制工具。 什么是视频录制软件? 顾名思义,视频捕…

【Vue 本地项目运行https服务】

配置本地开发环境的https访问 1、下载证书生成库2、创建证书颁发机构3、创建证书4、创建成功后会有4个文件在我们项目根目录5、定位到ca.crt 文件所在在位置 双击 安装证书6、在vue.config.js中引入证书; 1、下载证书生成库 npm install -g mkcert2、创建证书颁发机…