[Java JVM] Hotspot GC研究- 64位引用指针压缩技术

本文探讨了64位环境下,Hotspot JVM如何通过指针压缩技术节省内存资源。在64位CPU中,虽然对象引用使用64位地址,但实际堆内存远小于64位地址空间。Java通过虚拟机在存取引用时进行转换,实现了对外32位、内部32位的透明转换。开启指针压缩后,最大堆可达32GB,并通过对象8字节对齐优化了存储效率。实验显示,关闭指针压缩后,内存使用量翻倍。
摘要由CSDN通过智能技术生成

为什么需要指针压缩

在上一篇文章 [Java JVM] Hotspot GC研究- 开篇&对象内存布局 中介绍对象内存布局时, 曾提到过, 由于在64位CPU下, 指针的宽度是64位的, 而实际的heap区域远远用不到这么大的内存, 使用64bit来存对象引用会造成浪费, 所以应该做点事情来节省资源.


如何做

基于以下事实:

  • CPU 使用的虚拟地址是64位的, 访问内存时, 必须使用64位的指针访问内存对象
  • java对象是分配于具体的某个内存位置的, 对其访问必须使用64位地址
  • 对java对象内的引用字段进行访问时, 必须经过虚拟机这一层, 操作某个对象引用不管是getfield还是putfield, 都是由虚拟机来执行. 或者简单来说, 要改变java对象某个引用字段, 必须经过虚拟机的参与.

细心的你从上面一定可以看出一点线索, 由于存一个对象引用和取一个对象引用必须经过虚拟机, 所以完全可以在虚拟机这一层做些手脚. 对于外部来说, putfield提供的对象地址是64位的, 经过虚拟机的转换, 映射到32位, 然后存入对象; getfield指定目标对象的64位地址和其内部引用字段的偏移, 取32位的数据, 然后反映射到64位内存地址. 对于外部来说, 只看见64位的对象放进去, 拿出来, 内部的转换是透明的.


详细实现

请看代码:
hotspot/src/share/vm/oops/oop.hpp

// In order to put or get a field out of an instance, must first check
// if the field has been compressed and uncompress it.
oop oopDesc::obj_field(int offset) const {
  return UseCompressedOops ?
    load_decode_heap_oop(obj_field_addr<narrowOop>(offset)) :
    load_decode_heap_oop(obj_field_addr<oop>(offset));
}

void oopDesc::obj_field_put(int offset, oop value) {
  UseCompressedOops ? oop_store(obj_field_addr<narrowOop>(offset), value) :
                      oop_store(obj_field_addr<oop>(offset),       value);
}
  • 6
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值