JVM精进之路

JVM相关问题一网打尽
帅旋
关注
充电
IT宅站长,技术博主,架构师,全网id:arthinking。

开启指针压缩为什么还能支持32G内存寻址?

发布于 2024-09-19 | 更新于 2024-09-19

为什么64位平台要使用压缩指针?

大家好,我是帅旋,今天来聊聊压缩指针的问题。

我们知道,在64位操作系统中,指针默认占用64位,相比于32位,消耗多了一倍的内存,如果能够将指针压缩到32位,那么就可以显著减少内存占用,提高缓存命中率,提升程序的性能。这对于内存密集型应用来说尤为重要,因为节省的内存可以用于存储更多的数据或对象。此外,较小的指针也可以减少CPU的缓存压力,加快数据访问速度。

压缩指针优势主要体现在:

减少内存消耗

在64位系统中,未压缩的指针默认占用64位(8字节)。如果堆中存有大量的对象引用,这将显著增加内存的消耗。使用指针压缩,将指针大小减少至32位(4字节),可以减少每个对象引用消耗的内存量,从而降低整个应用的内存占用。

提高缓存利用率

较小的指针大小意味着更多的引用可以被缓存在CPU的缓存中。这有助于提高数据的局部性,减少内存带宽的使用,从而在许多情况下提升应用的性能。

减轻垃圾收集(GC)压力

使用较小的指针可以减少GC扫描和移动对象时所需处理的数据量。这不仅减轻了GC的压力,还可以提高GC的效率,尤其是在处理大量对象时。

为什么开启压缩指针还能只是32G内存寻址?

在Java的HotSpot JVM中,压缩指针(Compressed Oops)技术允许JVM使用32位的偏移量来引用堆中的对象,即使在一个大于4GB但小于或等于32GB的堆空间上。这种技术通过一个简单的算术运算(通常是乘法和加法)来实现,使得32位的偏移量能有效地映射到64位的实际地址空间。

压缩规则

堆内存小于4G时,不需要启用指针压缩,jvm会直接去除高32位地址,即使用低虚拟地址空间。

堆内存大于32G时,压缩指针会失效,会强制使用64位(8字节)来对java对象进行寻址,所以一般建议对内存设置为32G以内。

压缩参数

-XX:+UseCompressedOops:默认开启,压缩所有指针,ordinary object pointer。

-XX:+UseCompressedClassPointers:默认开启,压缩对象头里的类型指针Klass Pointer。

压缩原理

在压缩指针技术中,假设所有对象的起始地址都按一定的大小(如8字节)对齐。这意味着对象的实际地址的最后三个二进制位总是0(因为2^3=8),所以这三位可以在不丢失信息的情况下被省略。

省略这三位后,原本需要64位来存储的地址现在可以用61位来表示,如果堆大小小于32GB,实际上只需要35位就足够了(因为2^35=32GB)。

编码和解码过程

  • 编码(Compress):当JVM需要存储一个对象引用到32位的字段时,会将64位的实际地址右移三位(除以8),从而“压缩”这个地址。这种方式把原始的64位地址转换成了一个较小的值,通常称为“压缩的引用”或“偏移量”。
  • 解码(Uncompress):当需要访问实际对象时,JVM取出这个32位的压缩引用,然后将其左移三位(乘以8),并加上一个基地址(Heap Base Address),这个基地址是在JVM启动时确定的,它表示压缩指针偏移量的起始点。

本文作者: 帅旋

本文链接: https://www.itzhai.com/columns/faqs/jvm/why-pointer-compression-still-supports-32gb-memory-addressing.html

版权声明: 版权归作者所有,未经许可不得转载,侵权必究!联系作者请加公众号。

×
IT宅

关注公众号及时获取网站内容更新。

请帅旋喝一杯咖啡

咖啡=电量,给帅旋充杯咖啡,他会满电写代码!

IT宅

关注公众号及时获取网站内容更新。