当前位置:首页 > 科技  > 软件

硬核 JVM 压缩指针详解

来源: 责编: 时间:2023-10-13 14:37:06 176观看
导读一、前言当今,Java已经成为了世界上最流行的编程语言之一。在Java的生态系统中,JVM(Java虚拟机)是至关重要的组成部分。JVM 是 Java 程序运行的环境,它负责将 Java 字节码翻译成机器码,并执行程序。在 JVM 中,内存使用以及分

一、前言

当今,Java已经成为了世界上最流行的编程语言之一。在Java的生态系统中,JVM(Java虚拟机)是至关重要的组成部分。JVM 是 Java 程序运行的环境,它负责将 Java 字节码翻译成机器码,并执行程序。在 JVM 中,内存使用以及分配一直是个重要的问题。
CHG28资讯网——每日最新资讯28at.com

在 32 位系统中,一枚指针占用 4 字节,随着 64 位系统的逐渐普及,指针的大小也增长到了 8 个字节,JVM 为了降低内存占用,使用了指针压缩技术来降低内存的占用,接下来,我们将自顶向下的深入探讨 JVM 指针压缩的工作原理。CHG28资讯网——每日最新资讯28at.com

二、理解压缩指针

为什么 JVM 需要压缩指针?

在计算机中,指针的大小通常取决于计算机的字长。例如,在 32 位系统一字长为 4 字节,即一枚指针的占用内存空间大小为 4 字节。随着计算机性能的提升,内存价格的降低,64 位系统也开始逐渐普及。而在 64 位系统中,字长和指针也由原来的增长到 8 个字节,JVM 为了降低内存占用,开发了指针压缩算法,即:在 64 位系统中,指针依然使用 4 字节存储。
CHG28资讯网——每日最新资讯28at.com

数据指针与字长的关系

字长是指一台计算机中处理器可以一次性处理的二进制数字的位数。它通常是 8 位、16 位、32 位或 64 位,这意味着在一次处理中可以处理 8 个、16 个、32 个或 64 个二进制数字。字长越长,计算机处理数据的能力越强,但同时也会增加计算机的成本和复杂度。
CHG28资讯网——每日最新资讯28at.com

CPU 的上下文是寄存器,CPU 运算的本质就是不断从 CS IP 寄存器中取指令然后执行,CPU 运算所需的数据也是放在寄存器里,CPU 一次性处理的数据大小就是寄存器的大小。CHG28资讯网——每日最新资讯28at.com

图片图片CHG28资讯网——每日最新资讯28at.com

上图左侧是一段简单的 C 语言代码片段,右侧是该代码的汇编代码(即 CPU 执行这段代码的实际机器码的解释)。CHG28资讯网——每日最新资讯28at.com

图片图片CHG28资讯网——每日最新资讯28at.com

CPU 执行计算时,需要先将数据读取到寄存器,存取内存中的变量时,是直接操作变量所在地址及偏移量,而变量所在地址(即指针)也是存储在寄存器中的,因此寄存器大小直接决定了 CPU 所能访问内存的地址空间。因此,在 32 位系统中,寄存器的最大长度是 32 bit(即 4 个字节),因此最大支持访问 4GB 的内存空间,在 64 位系统中,寄存器最大 64 bit(即 8 字节)。而数据的指针由于需要指向整个内存空间,因此也就是 8 字节。8 字节大小的指针所能允许访问的最大地址为:16EB(16384PB=16777216TB=17179869184GB)的内存空间。CHG28资讯网——每日最新资讯28at.com

所以字长其实就等于寄存器的大小,指针为了能指向整个内存空间,通常也等于字长大小。CHG28资讯网——每日最新资讯28at.com

理解内存对齐

这是一段简单的 C 语言代码:
CHG28资讯网——每日最新资讯28at.com

#include <stdio.h>struct Test {    int a;    char b;    int c;} test;int main(void) {    test.a = 1;    test.b = 2;    test.c = 3;    printf("struct Test size: %d/n", sizeof(test));    return 0;}

在 C 语言中,结构体数据是连续的,Int 为 4 字节,Char 为 1 字节,所以 Struct Test 为 9 字节。CHG28资讯网——每日最新资讯28at.com

但是实际输出结果却是 12 字节:CHG28资讯网——每日最新资讯28at.com

图片图片CHG28资讯网——每日最新资讯28at.com

图片图片CHG28资讯网——每日最新资讯28at.com

通过汇编指令可以分析出,结构体 Test 的内存布局如下:CHG28资讯网——每日最新资讯28at.com

图片图片CHG28资讯网——每日最新资讯28at.com

可以看出,在 Char 类型数据后面被空出了 3 个字节的位置,原因如下:CHG28资讯网——每日最新资讯28at.com

计算机只能从 4 字节的整数倍开始寻址,如果在 Char b 后不进行空数据填充,则编译后的指令会很长,极大的降低 CPU 执行效率:CHG28资讯网——每日最新资讯28at.com

图片图片CHG28资讯网——每日最新资讯28at.com

所以在 JVM 中,对象的存储也是如此设计:CHG28资讯网——每日最新资讯28at.com

class Test {    int a;    char b;    int c;}

对象布局如下:CHG28资讯网——每日最新资讯28at.com

图片图片CHG28资讯网——每日最新资讯28at.com

可以看出 Char b 数据后空出了 3 个字节的内存空间作为 Padding, 以供后面的对象进行内存对齐。CHG28资讯网——每日最新资讯28at.com

为什么计算机只能从特定地址读取数据?

计算机之所以只能从特定地址开始读取数据,是由于在内存中存储的物理位置导致的。
CHG28资讯网——每日最新资讯28at.com

图片图片CHG28资讯网——每日最新资讯28at.com

这是一根内存条,上面有 4 个内存颗粒(Chip),在我们声明一个变量 Int a = 1;时,CPU 想一次从内存中同时取出 32 位数据,为了发挥并行传输数据的能力,同时与 4 个内存颗粒进行交互肯定比一个内存交互要快,因此数据 a 分别在 4 个颗粒中存储 0x01 0x00 0x00 0x00。CHG28资讯网——每日最新资讯28at.com

图片图片CHG28资讯网——每日最新资讯28at.com

每个内存颗粒 Chip 中有 8 个 bank,每次同时从 8 个 bank 中取一位数据。CHG28资讯网——每日最新资讯28at.com

图片图片CHG28资讯网——每日最新资讯28at.com

为了尽可能节约地址总线位数,变量 a 的每字节数据在各 Chip 中相对位置是相同的,每字节中的每位数据在 bank 中的行数和列数也是相同的。CHG28资讯网——每日最新资讯28at.com

总结,为了能利用有限的地址总线,尽量快速寻址到尽可能多的数据,在设计计算机时取了巧,CPU 同时只能访问 32 个相对地址相同的数据位,表现上就是只能从被 4 字节整除的地址开始寻址。CHG28资讯网——每日最新资讯28at.com

理解指针压缩

在 64 位系统中,JVM 为了降低 8 字节的指针对内存的占用,使用了指针压缩的技术,将 8 字节的指针压缩为 4 字节。
CHG28资讯网——每日最新资讯28at.com

前面说到,JVM 出于性能考虑,对数据做了对齐到 4 字节的处理,因此指针的值末尾 5 bit 始终为 0B11111。JVM 的指针压缩算法就是,把本来应该使用 8 个字节的指针,直接改为 4 字节的进行代替,那么 4 字节的指针实际最高可以表示 32G 的内存空间。这也就是为什么当物理内存超过 32G 时,需要关闭 JVM 指针压缩。CHG28资讯网——每日最新资讯28at.com

三、实战解码指针

工具介绍

HSDB

HSDB(HotSpot Debugger),是一个用于 HotSpot 虚拟机的调试工具。它提供了一种可视化的方式来查看和调试 Java 应用程序在 JVM 上的运行情况。HSDB 可以用于分析线程、堆、类、对象、方法、编译器和代码缓存等方面的信息。它还可以用于监视虚拟机性能和调试垃圾回收器。HSDB 是一个非常强大的工具,可以帮助开发人员更好地理解和优化 Java 应用程序的性能。CHG28资讯网——每日最新资讯28at.com

官方提供的 HSDB 命令行不是很好用,比如命令补全、命令提示、光标移动、命令历史记录等都不存在,所以本次分享讲利用 PerfMa 开源的 XPocket 工具,配合 HSDB 插件来操作。CHG28资讯网——每日最新资讯28at.com

XPocket 工具

XPocket 是 PerfMa 为解决性能问题而生的开源的插件容器,它是性能领域的乐高,将定位或者解决各种性能问题的常见的 Linux 命令,JDK 工具,知名性能工具等适配成各种 XPocket 插件,并让它们可以相互联动一键解决特定的性能问题。目前 XPocket 插件生态已经实现了 HSDB、JDB、JConsole、Perf、Arthas 等多个优秀的开源性能工具的插件化集成。CHG28资讯网——每日最新资讯28at.com

快速开始

下载 XPocket,然后解压运行。
CHG28资讯网——每日最新资讯28at.com

wget https://a.perfma/xpocket/download/XPocket.tar.gztar -xvf  XPocket.tar.gzsh xpocket/xpocket.sh

图片图片CHG28资讯网——每日最新资讯28at.com

# 切换至 HSDB 插件空间XPocket [system] > use jhsdb@JDK# 启动 clhsdb 命令行XPocket [jhsdb] > clhsdb# attach 到目标进程XPocket [jhsdb] > attach 29516

利用 HSDB 查看 JVM 对象内存布局

准备工作

编写一个测试类,启动 JVM 进程。CHG28资讯网——每日最新资讯28at.com

@Data@Componentpublic class BeanTest {    private long l = 1;    private BeanTest pointer = this;    private int i = 2;    private boolean b = false;    private char c = 3;    private BeanTest[] arr = {this};}

想要查看对象的内存布局,首先要找到这个对象所在位置,JVM 的对象分布在堆上,可以通过 Universe 命令确定堆内的相关区域对应位置。CHG28资讯网——每日最新资讯28at.com

# 执行以下命令,切换至 HSDB 插件XPocket [system] > use jhsdb@JDK# 启动 HSDB 插件XPocket [jhsdb] > clhsdb# 通过 jps 命令,查询 JVM 进程的 pid,attach 到这个 JVM 进程XPocket [jhsdb] > attach 29516# 执行 universe 命令,查看堆内存分布情况XPocket [jhsdb : 29516] > universe

内存分布情况如下:CHG28资讯网——每日最新资讯28at.com

图片图片CHG28资讯网——每日最新资讯28at.com

括号内的第一个值为内存起始位置,第二个值为已使用的位置,第三个值为该区域最大地址。以上图 eden 区为例:CHG28资讯网——每日最新资讯28at.com

eden 区空间范围为:0x00000000fab00000 ~ 0x00000000fef00000,相减得到 71303168,68MB。CHG28资讯网——每日最新资讯28at.com

eden 区已使用空间为:0x00000000fab00000 ~ 0x00000000fafd2a60,相减得到 5057120,4.82M。CHG28资讯网——每日最新资讯28at.com

找到我们定义的对象

我们要找的对象是受 Spring 管理的,所以很容易判断,通常情况下都会在老年代里。那么我们直接在老年代内检索这个对象即可。由于 Oop(简单对象指针)是所有 Java 对象的基类,所以我们可以利用 Scanoops 命令来检索这个对象。CHG28资讯网——每日最新资讯28at.com

XPocket [jhsdb : 29516] > scanoops 0x00000000f0000000 0x00000000f1265ca8 com.poizon.robot.test.BeanTest

检索到的结果如下:CHG28资讯网——每日最新资讯28at.com

图片图片CHG28资讯网——每日最新资讯28at.com

0x00000000f1060898 是这个对象实例的内存地址,也就是该对象的指针值。CHG28资讯网——每日最新资讯28at.com

查看对象内存布局

然后我们就可以通过 Inspect 命令来查看该对象的内存布局了。CHG28资讯网——每日最新资讯28at.com

XPocket [jhsdb : 29516] > inspect 0x00000000f1060898

得到结果如下:CHG28资讯网——每日最新资讯28at.com

图片图片CHG28资讯网——每日最新资讯28at.com

注意:这里显示的数据是按照类变量顺序来展示的,并非实际结构CHG28资讯网——每日最新资讯28at.com

由图返回结果可以看出, BeanTest 对象大小为 40 字节,当前系统为 X64 架构,一个字长为 8 字节,即此对象占用 5 个字长。执行 Mem 命令,获取整个对象(5 个字长)的数据。CHG28资讯网——每日最新资讯28at.com

XPocket [jhsdb : 29516] > mem 0x00000000f1060898 5

得到结果如下:CHG28资讯网——每日最新资讯28at.com

图片图片CHG28资讯网——每日最新资讯28at.com

左侧为当前字长的数据起始地址,右侧为数据值。CHG28资讯网——每日最新资讯28at.com

我们再来复习一遍对象头(Oop数据),前 8 位是 Mark Word,后 8 位中,如果开启了指针压缩,则前 4 位为当前实例所在类的指针,后 4 位填充当前对象 <=4 字节的数据(Gap Padding);如果未开启指针压缩,则该 8 位为当前实例对所在类的指针。CHG28资讯网——每日最新资讯28at.com

查找类的指针

我们这次启动的进程开启了指针压缩,把第二个字长的数据(0x000000022007a2bb)按 4 字节拆成两部分:CHG28资讯网——每日最新资讯28at.com

0x00000002:BeanTest 对象中只有一个值为 2 ,所以该值是Int i = 2;CHG28资讯网——每日最新资讯28at.com

0x2007a2bb(类指针):前面说过,指针压缩的原理只是简单的把 8 字节指针削减为 4 字节,因为后 5 位始终为 0,因此若要还原压缩后的指针实际内存地址,直接把指针值 * 8即可。CHG28资讯网——每日最新资讯28at.com

BeanTest 类所在地址为:0x2007a2bb * 8 = 0x1003D15D8CHG28资讯网——每日最新资讯28at.com

执行 Inspect 命令,查看 BeanTest 类结构。CHG28资讯网——每日最新资讯28at.com

XPocket [jhsdb : 29516] > inspect 0x1003D15D8

结果如下:CHG28资讯网——每日最新资讯28at.com

图片图片CHG28资讯网——每日最新资讯28at.com

证实

BeanTest 在 JVM 对象为 c++ 的 InstanceKlass 实例,可以看出 _name 属性为 Symbol,接下来查看 InstanceKlass _name 属性,证实当前为 BeanTest 类的实例,执行 Symbol 命令查看 _name 的值:CHG28资讯网——每日最新资讯28at.com

XPocket [jhsdb : 29516] > symbol 0x00007f1838abb740

图片图片CHG28资讯网——每日最新资讯28at.com

证实 0x1003D15D8 所在的内存地址,即是 com.poizon.robot.test.BeanTest 的 Class 对象。CHG28资讯网——每日最新资讯28at.com

四、总结

在我们日常开发中遇到的一点小小的,看似不起眼的奇怪的规范,深挖之下往往能够牵扯出一大串知识体系,保持好奇心刨根问底同样也是很重要学习方法。有兴趣的同学也可以自己尝试找一下示例类中其他属性所对应的 Class 指针,说不定还可以对网上的一些文章做一次勘误呢~CHG28资讯网——每日最新资讯28at.com

本文链接:http://www.28at.com/showinfo-26-13297-0.html硬核 JVM 压缩指针详解

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: WhatsApp 仅用 32 名工程师就能支持每天 500 亿条消息的八个原因

下一篇: 如何使用Otseca搜索和转储系统配置并生成HTML报告

标签:
  • 热门焦点
  • 帅气纯真少年!日本最帅初中生选美冠军出炉

    帅气纯真少年!日本最帅初中生选美冠军出炉

    日本第一帅哥初一生选美大赛冠军现已正式出炉,冠军是来自千叶县的宗田悠良。日本一直热衷于各种选美大赛,从&ldquo;最美JK&rdquo;起到&ldquo;最美女星&r
  • 使用AIGC工具提升安全工作效率

    使用AIGC工具提升安全工作效率

    在日常工作中,安全人员可能会涉及各种各样的安全任务,包括但不限于:开发某些安全工具的插件,满足自己特定的安全需求;自定义github搜索工具,快速查找所需的安全资料、漏洞poc、exp
  • 自律,给不了Keep自由!

    自律,给不了Keep自由!

    来源 | 互联网品牌官作者 | 李大为编排 | 又耳 审核 | 谷晓辉自律能不能给用户自由暂时不好说,但大概率不能给Keep自由。近日,全球最大的在线健身平台Keep正式登陆港交所,努力
  • 签约井川里予、何丹彤,单视频点赞近千万,MCN黑马永恒文希快速崛起!

    签约井川里予、何丹彤,单视频点赞近千万,MCN黑马永恒文希快速崛起!

    来源:视听观察永恒文希传媒作为一家MCN公司,说起它的名字来,可能大家会觉得有点儿陌生,但是说出来下面一串的名字之后,或许大家就会感到震惊,原来这么多网红,都签约这家公司了。根
  • 大厂卷向扁平化

    大厂卷向扁平化

    来源:新熵作者丨南枝 编辑丨月见大厂职级不香了。俗话说,兵无常势,水无常形,互联网企业调整职级体系并不稀奇。7月13日,淘宝天猫集团启动了近年来最大的人力制度改革,目前已形成一
  • ESG的面子与里子

    ESG的面子与里子

    来源 | 光子星球撰文 | 吴坤谚编辑 | 吴先之三伏大幕拉起,各地高温预警不绝,但处于厄尔尼诺大&ldquo;烤&rdquo;之下的除了众生,还有各大企业发布的ESG报告。ESG是&ldquo;环境保
  • 超闭合精工铰链 彻底消灭缝隙 三星Galaxy Z Flip5与Galaxy Z Fold5发布

    超闭合精工铰链 彻底消灭缝隙 三星Galaxy Z Flip5与Galaxy Z Fold5发布

    2023年7月26日,三星电子正式发布了Galaxy Z Flip5与Galaxy Z Fold5。三星新一代折叠屏手机采用超闭合精工铰链,让折叠后的缝隙不再可见。同时,配合处
  • 7月4日见!iQOO 11S官宣:“鸡血版”骁龙8 Gen2+200W快充加持

    7月4日见!iQOO 11S官宣:“鸡血版”骁龙8 Gen2+200W快充加持

    上半年已接近尾声,截至目前各大品牌旗下的顶级旗舰都已悉数亮相,而下半年即将推出的顶级旗舰已经成为了数码圈爆料的主流,其中就包括全新的iQOO 11S系
  • 2022爆款:ROG魔霸6 冰川散热系统持续护航

    2022爆款:ROG魔霸6 冰川散热系统持续护航

    喜逢开学季,各大商家开始推出自己的新产品,进行打折促销活动。对于忠实的端游爱好者来说,能够拥有一款梦寐以求的笔记本电脑是一件十分开心的事。但是现在的
Top