JVM-指针压缩
1. 关键前提
- 对象地址对齐:JVM中所有对象地址按8字节对齐(最低3位必为
000
) - 32GB堆内存范围:
0x000000000
~0x7FFFFFFFF
(35位地址空间) - 压缩目标:将64位指针压缩为32位存储
2. 32GB堆最大地址的二进制分析
(1)最大64位地址(32GB边界)
十六进制:0x7FFFFFFFF
完整二进制:
0000 0000 0000 0000 0000 0000 0111 1111 1111 1111 1111 1111 1111 1111 1111 1000
(实际有效35位:第0-34位)
(2)关键特征
有效地址部分:111 1111 1111 1111 1111 1111 1111 1111 1111 1000(35位)
对齐特征:_______________________________↑↑↑固定为000(3位)
3. 压缩过程(64位→32位)
(1)右移3位(丢弃对齐位)
原始地址:111 1111 1111 1111 1111 1111 1111 1111 1111 1000
右移3位: 000 1111 1111 1111 1111 1111 1111 1111 1111 1111
(2)截取低32位
截取结果:1111 1111 1111 1111 1111 1111 1111 1111(0xFFFFFFFF)
存储内容:32位压缩指针 = 0xFFFFFFFF
4. 解压过程(32位→64位)
(1)左移3位(恢复对齐位)
压缩指针:1111 1111 1111 1111 1111 1111 1111 1111
左移3位:1111 1111 1111 1111 1111 1111 1111 1111 1000
(2)补零扩展至64位
最终地址:0000 0000 0000 0000 0000 0000 0111 1111 1111 1111 1111 1111 1111 1111 1111 1000= 0x000000007FFFFFFFF(原始地址)
5. 关键点总结
为什么是3位?
- 8字节对齐 ⇒ 地址是8的倍数 ⇒ 二进制末尾3位=
000
⇒ 这3位无需存储。
- 8字节对齐 ⇒ 地址是8的倍数 ⇒ 二进制末尾3位=
32位如何覆盖35位空间?
- 压缩后32位的每个单位实际代表8字节(因为左移3位相当于
×8
),因此总地址空间为:
- 压缩后32位的每个单位实际代表8字节(因为左移3位相当于
2^32×8=2^35=32GB
32位能表示的地址个数为:2^32=4G
每个地址8字节对齐:4G*8 =32G
问题:不右移已经能表示32G内存了,为什么还要右移?
操作 | 目的 | 数学本质 | 硬件支持优势 |
---|---|---|---|
右移3位 | 将字节地址转换为块索引 | 物理地址 ÷ 8 | 取代低速除法指令 |
左移3位 | 将块索引还原为物理地址 | 块索引 × 8 | 匹配CPU缓存行 |