有关压缩 oops 的详细说明,请参阅“Hotspot JVM 中的压缩 oops” https://wiki.openjdk.java.net/display/HotSpot/CompressedOops约翰·罗斯@Oracle 的文章。
TL;DR 版本是:
- 在现代计算机体系结构中,内存地址是字节地址,
- Java object references are addresses that point to the start of a word1,
- on a 64-bit machine, word alignment means that that the bottom 3 bits of an object reference / address are zero2
- 因此,通过将地址右移 3 位,我们可以将 64 位地址的 35 位“压缩”为 32 位字,
- 并且,可以通过向左移动 3 位来完成解压缩,这会将这 3 个零位放回原处,
- 35 位寻址允许我们使用适合 64 位机器上 32 位(半)字的压缩 oop 来表示最多 32 GB 堆内存的对象指针。
Note that this only works on a 64-bit JVM. We still need to be able to address the memory containing that (up to) 32 GB heap1, and that means 64-bit hardware addresses (on modern CPUs / computer architectures).
Note also that there is a small penalty in doing this; i.e. the shift instructions required to translate between regular and compressed references. However, the flip side is that less actual memory is consumed3, and memory caches are typically more effective as a consequence.
1 - This is because modern computer architectures are optimized for word-aligned memory access.
2 - This assumes that you haven't used -XX:ObjectAlignmentInBytes
to increase the alignment from its default (and minimum) value of 8 bytes.
3 - In fact, the memory saving is application specific. It depends on the average object alignment wastage, ratios of reference to non-reference fields and so on. It gets more complicated if you consider tuning the object alignment.
To simplify the problem how can we address up to 24 memory addresses using just 2 bits? What can be a possible encoding/decoding of such an address scheme?
You can't address 24 byte addresses. But you can address 22 word addresses (assuming 32-bit words) using 2-bit word addresses. If you can assume that all byte addresses are word-aligned, then you can compress a 4-bit byte address as 2-bit word address by shifting it by 2-bit positions.