浅析JVM内存指针压缩

jvm指针压缩指的是:

  • java对象的Object Head里的Klass Pointer由8字节压缩为4字节,Klass Pointer指向当前对象的Class对象的内存位置
  • java对象内部的复杂类型属性的引用由8字节压缩为4字节,就是说当前对象持有复杂类型的属性对象的内存位置
  • 数组对象的长度由8字节压缩为4字节,同时数组对象持有的每个元素的内存引用由8字节压缩为4字节

以上机制生效的前提是jvm在64位机器上,32位机器内存上限是4G,内存指针默认是4字节。

在64位机器上当分片的jvm内存小于32G时,JVM默认开启指针压缩,此时指针表示的不是引用对象的实际内存地址,是一个相对的地址。如何用一个32位的数字表示内存32G内存内的任意地址?,这个是我之前没想明白的,今天这篇博客主要就是解释这个问题。

在大于32G的机器上分配32G内存给jvm应用,首先这32G内存是需要连续的,因此jvm内存的低位相较于机器内存的低位有一个偏移量,计 offset0,这个偏移量在通过内存指针计算实际内存地址时是需要考虑进去的。

32G内存有 1024*1024*1024*32 = 2^35个字节,4个字节是32位,最大能表示 2^32-1 ,这中间还差了 2^3 的数量级,该如何圆场?网上说4个字节有40多亿,表示40多亿个对象。但是一个对象至少16字节,2^32 * 16 = 2^36 超过了 2^35 的字节上限了,所以指针指向的也不是实际的对象地址。

后来想到了java对象大小是有一个对齐机制的:Object Header + 实例数据 + 对齐填充对齐填充保证java对象的大小始终是8字节的倍数,也就是一个对象的大小都是8字节的倍数,他们有一个公约数8。把 2^35 / 8 = 2^32 刚好等于4个字节所能表示的数值的区间。把jvm内存按8字节划分为一个一个格子区间,指针指向的是这个格子区间的序号

根据指针计算内存的实际地址的公式近视为: 内存地址(字节单位) = jvm内存偏移量 + 指针 * 8

通过这种巧妙的设计,能够将jvm内对象的地址从8字节压缩为4字节,极大的提高jvm对内存的使用效率。当jvm超过32G时,这种算法就失效了,在8字节的指针情况下,需要内存达到40-50G时才能和4字节指针时32G内存具有相同的存储空间。

发布了107 篇原创文章 · 获赞 95 · 访问量 24万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 书香水墨 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览