#### **基础概念:指针压缩与地址对齐**
1. **指针压缩的作用**
在64位JVM中,普通指针占用8字节。启用压缩指针后,通过 **地址对齐** 和 **位移操作**,将指针压缩到4字节。这相当于用32位的空间存储原本需要64位的信息,节省内存占用。
2. **为什么要用8字节对齐?**
JVM强制所有对象按 **8字节对齐**(类似“内存格子”的最小单位是8字节)。例如:
• 对象A的起始地址可能是`0x1000`(十进制4096,是8的倍数);
• 对象B的起始地址可能是`0x1008`(十进制4104,也是8的倍数)。
**对齐后的地址特点**:二进制地址的后三位始终为`000`(例如`0x1000`的二进制是`0001 0000 0000 0000`,最后三位是`000`)。
---
#### **压缩指针的寻址计算**
1. **压缩存储的原理**
• 由于地址是8字节对齐的,后三位`000`无实际意义,可以 **舍弃不存**。
• 例如,对象地址`0x1000`(二进制后三位`000`),压缩后存储的是`0x1000 >> 3 = 0x200`(32位数值)。
2. **解压还原的步骤**
• 使用时将压缩后的32位值 **左移3位**(相当于乘以8),补上被舍弃的后三位`000`。
• 例如,压缩值`0x200`还原为真实地址:`0x200 << 3 = 0x1000`。
3. **最大寻址范围的计算**
• 32位能表示的最大值是`2^32`,每个值对应8字节的内存块。
• **总寻址范围** = `2^32 × 8B = 32GB`
(相当于用32个二进制位管理32GB内存,每个位代表8字节的“内存格子”)。
---
#### **为什么说“跨度是8字节,而非单字节”?**
• **单字节寻址**:普通指针直接表示每个字节的地址,例如32位指针能寻址`2^32 × 1B = 4GB`。
• **压缩指针的“块寻址”**:
• 每个压缩指针代表一个 **8字节的块**(类似快递柜的“格子编号”,每个编号对应一个8字节的格子)。
• 32位能表示`2^32`个块,总容量为`2^32 × 8B = 32GB`。
---
#### **实际例子**
假设堆内存中有以下对象地址(16进制):
• `0x0000` → 二进制末尾`000`
• `0x0008` → 二进制末尾`000`
• `0x0010` → 二进制末尾`000`
**压缩存储**:
JVM将这些地址统一右移3位,得到压缩值`0x000`、`0x001`、`0x002`(32位数值)。
**解压还原**:
使用时左移3位,恢复为原始地址`0x0000`、`0x0008`、`0x0010`。
---
#### **关键总结**
• **8字节对齐是压缩的基石**:通过舍弃地址末尾的3位`000`,将寻址粒度从1字节扩大到8字节,实现“用32位管32GB”。
• **性能与空间的平衡**:
• **优点**:内存占用减少50%,提升缓存效率。
• **限制**:堆内存超过32GB时,压缩失效(需回退到8字节指针)。
下一篇:JVM 地址对齐
- 请尽量让自己的回复能够对别人有帮助
- 支持 Markdown 格式, **粗体**、~~删除线~~、
`单行代码`
- 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
- 图片支持拖拽、截图粘贴等方式上传