当前位置: 首页 > news >正文

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

相关文章:

JVM-HotSpot虚拟机对象探秘

目录 一、对象的实例化 (一)创建对象的方式 (二)创建对象的步骤 二、对象的内存布局 (一)对象头 (二)实例数据 (三)对齐填充 三、 对象的访问定位 &…...

大模型技术的发展:开源和闭源,究竟谁强谁弱又该何去何从?

一、开源和闭源的优劣势比较 开源和闭源软件都有各自的优劣势,具体比较如下: 安全性:闭源软件的安全性相对较高,因为其源代码不公开,攻击者难以找到漏洞进行攻击。而开源软件由于源代码公开,容易被攻击者发…...

Python学习笔记--自定义元类

四、自定义元类 到现在,我们已经知道元类是什么鬼东西了。 那么,从始至终我们还不知道元类到底有啥用。 只是了解了一下元类。 在了解它有啥用的时候,我们先来了解下怎么自定义元类。 因为只有了解了怎么自定义才能更好的理解它的作用。…...

软件测试 —— 常见的自动化测试架构!

一个自动化测试架构就是一个集成体系,其中定义了一个特殊软件产品的自动化测试规则。这一体系中包含测试功能函数库、测试数据源、测试对象识别标准,以及各种可重用的模块。这些组件作为小的构建模块,被组合起来代表某种商业流程。自动化测试…...

Python 的 @lru_cache() 装饰器

在 Python 标准库的 functools 模块中,有个 lru_cache 装饰器,用于为一个函数添加缓存系统: 存储函数的输入和对应的输出当函数被调用,并且给出了已经缓存过的输入,那么函数不会再运行,而是直接从缓存中获…...

Swift制作打包framework

新建framework项目 设置生成fat包,包括模拟器x86_64和arm64 Buliding Settings -> Architectures -> Build Active Architecture Only 设置为NO 设置打包环境,选择release edit Scheme -> run -> Build configuration 设置为 Release 设置…...

无线WiFi安全渗透与攻防(N.2)WPA渗透-使用airolib-ng创建彩虹表加速

WPA渗透-使用airolib-ng创建彩虹表加速 WPA渗透-使用airolib-ng创建彩虹表加速1.什么是彩虹表?2.渗透wifi1.创建数据库名2.将字典导入数据库3.生成渗透wifi密码的PMK4.生成需要渗透wifi的彩虹表5.渗透wifiWPA渗透-使用airolib-ng创建彩虹表加速 1.什么是彩虹表? 彩虹表是一…...

整形数据和浮点型数据在内存中的存储差别

愿所有美好如期而遇 我们先来看代码,猜猜结果是什么呢? int main() {//以整型数据的方式存储int n 10;float* m (float*)&n;//以整型数据的方式读取printf("%d\n", n);//以浮点型数据的方式2读取printf("%f\n", *m);printf(&…...

【Python基础篇】运算符

博主:👍不许代码码上红 欢迎:🐋点赞、收藏、关注、评论。 格言: 大鹏一日同风起,扶摇直上九万里。 文章目录 一 Python中的运算符二 算术运算符1 Python所有算术运算符的说明2 Python算术运算符的所有操作…...

开启数据库审计 db,extended级别或os级别)并将审计文件存放到/opt/oracle/audit/下

文章目录 1、登录到数据库2、查看审计状态3、创建审计目录4、启用审计5、设置审计文件路径6、再次查看结果 1、登录到数据库 使用SQL*Plus或者其他Oracle数据库客户端登录到数据库。 sqlplus / as sysdba;2、查看审计状态 show parameter audit;目前是DB状态,并且…...

02.webpack中多文件打包

1.module,chunk,bundle的区别 moudle - 各个源码文件,webpack中一切皆是模块chunk - 多模块合并成的,如entry, import(), splitChunkbundle - 最终的输出文件 2.多文件打包配置 2.1 webpack.common.js const path require(path) const HtmlWebpackPl…...

IEEE Standard for SystemVerilog Chapter 22. Compiler directives

22.1 General 此子句描述以下编译器指令(按字母顺序列出): __FILE__ [22.13] __LINE__ [22.13] begin_keywords [22.14] celldefine [22.10] default_net…...

机器学习中的独立和同分布 (IID):假设和影响

一、介绍 在机器学习中,独立和同分布 (IID) 的概念在数据分析、模型训练和评估的各个方面都起着至关重要的作用。IID 假设是确保许多机器学习算法和统计技术的可靠性和有效性的基础。本文探讨了 IID 在机器学习中的重要性、其假设及其对模型开…...

PTP软硬件时间戳

软硬件时间戳 抄袭来源:http://www.bdtime.com.cn/pinlv/4296.html PTP 是一种网络协议,用于在计算机网络中进行时钟校准和时间同步。硬件时间戳和软件时间戳是在实现 PTP 时常见的两种方式,它们在精度、可靠性、实时性以及资源消耗等方面存…...

使用ADS进行serdes仿真时,Tx_Diff中EQ的设置对发送端波形的影响。

研究并记录一下ADS仿真中Tx_Diff的EQ设置。原理图如下: 最上面是选择均衡方法Choose equalization method:Specify FIR taps,Specify de-emphasis和none。 当选择Specify de-emphasis选项时,下方可以输入去加重具体的dB值&#x…...

数据库迁移(DBeaver版本)

最近需要做一个数据库迁移, 测试环境开发的差不多了,需要将脚本迁移到生产。 中间了试了一些工具,比如Jetbrain出品的datagrip,这个数据库工具平时还是很好用的,但是数据迁移感觉不是那么好用,所以还是用到…...

【c++STL常见排序算法sort,merge,random_shuffle,reverse】

文章目录 C STL 常见排序算法详解1. sort 算法2. merge 算法3. random_shuffle 算法4. reverse 算法 C STL 常见排序算法详解 1. sort 算法 功能&#xff1a;sort 用于对容器内的元素进行升序排序。示例代码&#xff1a;#include <iostream> #include <algorithm>…...

STM32/N32G455国民科技芯片驱动DS1302时钟---笔记

这次来分享一下DS1302时钟IC&#xff0c;之前听说过这个IC&#xff0c;但是一直没搞过&#xff0c;用了半天时间就明白了原理和驱动&#xff0c;说明还是很简单的。 注&#xff1a;首先来区分一下DS1302和RTC时钟有什么不同&#xff0c;为什么不直接用RTC呢&#xff1f; RTC不…...

基于PLC的污水厌氧处理控制系统(论文+源码)

1. 系统设计 污水厌氧由进水系统通过粗格栅和清污机进行初步排除大块杂质物体以及漂浮物等&#xff0c;到达除砂池中。在除砂池系统中细格栅进一步净化污水厌氧中的细小颗粒物体&#xff0c;将污水厌氧中的细小沙粒滤除后进入氧化沟反应池。在该氧化沟系统中进行生化处理&…...

Unity之NetCode多人网络游戏联机对战教程(9)--NetworkAnimator组件

文章目录 前言NetworkAnimatorAnimator的Trigger属性服务器权威模式&#xff08;Server Authoritative Mode&#xff09;客户端权威模式 (Owner Authoritative Mode)学习文档 前言 这个组件是NetCode常用的组件之一&#xff0c;NetworkAnimator跟NetworkTransform一样&#xf…...

设计模式和设计原则回顾

设计模式和设计原则回顾 23种设计模式是设计原则的完美体现,设计原则设计原则是设计模式的理论基石, 设计模式 在经典的设计模式分类中(如《设计模式:可复用面向对象软件的基础》一书中),总共有23种设计模式,分为三大类: 一、创建型模式(5种) 1. 单例模式(Sing…...

【入坑系列】TiDB 强制索引在不同库下不生效问题

文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...

理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端

&#x1f31f; 什么是 MCP&#xff1f; 模型控制协议 (MCP) 是一种创新的协议&#xff0c;旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议&#xff0c;它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...

Psychopy音频的使用

Psychopy音频的使用 本文主要解决以下问题&#xff1a; 指定音频引擎与设备&#xff1b;播放音频文件 本文所使用的环境&#xff1a; Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...

解决本地部署 SmolVLM2 大语言模型运行 flash-attn 报错

出现的问题 安装 flash-attn 会一直卡在 build 那一步或者运行报错 解决办法 是因为你安装的 flash-attn 版本没有对应上&#xff0c;所以报错&#xff0c;到 https://github.com/Dao-AILab/flash-attention/releases 下载对应版本&#xff0c;cu、torch、cp 的版本一定要对…...

AI编程--插件对比分析:CodeRider、GitHub Copilot及其他

AI编程插件对比分析&#xff1a;CodeRider、GitHub Copilot及其他 随着人工智能技术的快速发展&#xff0c;AI编程插件已成为提升开发者生产力的重要工具。CodeRider和GitHub Copilot作为市场上的领先者&#xff0c;分别以其独特的特性和生态系统吸引了大量开发者。本文将从功…...

Linux --进程控制

本文从以下五个方面来初步认识进程控制&#xff1a; 目录 进程创建 进程终止 进程等待 进程替换 模拟实现一个微型shell 进程创建 在Linux系统中我们可以在一个进程使用系统调用fork()来创建子进程&#xff0c;创建出来的进程就是子进程&#xff0c;原来的进程为父进程。…...

基于TurtleBot3在Gazebo地图实现机器人远程控制

1. TurtleBot3环境配置 # 下载TurtleBot3核心包 mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src git clone -b noetic-devel https://github.com/ROBOTIS-GIT/turtlebot3.git git clone -b noetic https://github.com/ROBOTIS-GIT/turtlebot3_msgs.git git clone -b noetic-dev…...

保姆级教程:在无网络无显卡的Windows电脑的vscode本地部署deepseek

文章目录 1 前言2 部署流程2.1 准备工作2.2 Ollama2.2.1 使用有网络的电脑下载Ollama2.2.2 安装Ollama&#xff08;有网络的电脑&#xff09;2.2.3 安装Ollama&#xff08;无网络的电脑&#xff09;2.2.4 安装验证2.2.5 修改大模型安装位置2.2.6 下载Deepseek模型 2.3 将deepse…...

【Redis】笔记|第8节|大厂高并发缓存架构实战与优化

缓存架构 代码结构 代码详情 功能点&#xff1a; 多级缓存&#xff0c;先查本地缓存&#xff0c;再查Redis&#xff0c;最后才查数据库热点数据重建逻辑使用分布式锁&#xff0c;二次查询更新缓存采用读写锁提升性能采用Redis的发布订阅机制通知所有实例更新本地缓存适用读多…...