The normal object pointer OOPs
An ordinary Object Pointer (OOP) is a pointer that HotSpot uses to point to the memory address of the object instance. OOP is usually the same size as the number of bits in the JVM. In a 32-bit JVM, OOP is 32 bits. In 64-bit JVMS, OOP is 64-bit in size
The compression pointer is CompressedOops
Why do I need to compress Pointers
In 64-bit JVMS, OOP is 64-bit in size and can be expressed in the range of 0 to 2^64 bits, or 0 to 2,147,483,648 GB if the number represents a memory address
However, using OOP in 64bit presents some problems
- OOP storage overhead increases: OOP is 32bit in 32-bit JVMS, and 64bit in 64-bit JVMS, doubling in size
- Reduced CPU cache hit ratio: THE SIZE of the CPU cache is limited, and as THE OOP becomes larger, there is less to store and caching needs to be swapped out more frequently
- “Performance” excess: 64-bit can represent up to 2,147,483,648 GB of memory, which modern operating systems do not currently support and programs do not need
It’s a bit wasteful to store OOP in 64 bits, but is it ok to store OOP in 32 bits in a 64 bit JVM? The 32-bit heap size ranges from 0 to 2^32, and if the memory address is a memory address, it ranges from 0 to 4GB. 4GB heap size may not be enough for some programs. Therefore, using 32 bits to directly express memory address is not appropriate!
Starting with the Oracle JDK 1.6 Update 14, the JVM provides a new solution on 64-bit systems that increases the maximum expressible memory address space from 4GB to 32GB in 32-bit space, saving storage space and increasing expressivity. It’s called CompressedOops.
The implementation principle of compression pointer
JVM implementations of CompressedOops are based on the premise that in 64-bit JVMS, object instances must be multiples of 64bit size
For information about object size and memory structure, see JAVA Object Memory Layout
The JVM uses these features to implement CompressedOops, as follows
Object’s direct memory address = base address of the heap + (32bit CompressedOops * 64bit)
- Object’s direct memory address: The memory address of an object instance that is directly accessible
- Base address: The starting address of the heap memory space
There is nothing to be said for the first two blocks, the focus is on the later 32bit CompressedOops * 64bit
We still use 32 bits to store values, but instead of representing the actual memory address, we use this value to represent offsets, which are 64 bits in size.
For the object shown above, with the compression pointer enabled, CompressedOops reads as follows
The simple idea is that
The JVM still uses 32-bit space to store the value, but the unit of the value is changed. The original unit of the value is the bit, which directly corresponds to the memory address. When the compression pointer is enabled, the unit of the value is the offset
Using this idea of “unit magnification”, the value can be magnified arbitrarily, but after magnification, the range of representation from the original continuous 0 ~ 2^32 to the discrete [0*n, 1*n, 2*n,… 2^32*n], where n is the multiple of magnification. (So, at the bottom of the computer is math.)
The JVM chose 64 because “in a 64-bit JVM, the object instance must be a multiple of 64bit size”, so that even if the memory address is changed from continuous to discrete, the object instance can still be accessed
Zero Based Compressd Oops
Zero Based CompressdOops, a further improvement on CompressdOops, forces the heap base to be assigned from Zero (with OS support) by changing the random address assignment nature of the normal pointer.
The scope of the compressed pointer
First, only the Oracle JDK version 1.6 Update 14 is available and the JVM is 64-bit, not 32-bit.
Second, even if compressed Pointers are enabled, the JVM does not compress all Pointers. See below for details on which Pointers are compressed and which Pointers are not
Oops ** that will be compressed in the heap
- Klass Pointer in the object header
- Each OOP instance field
- Each element of an OOP array (objArray)
Pointers that cannot be compressed. In the interpreter, oops is never compressed, including
- Pointer to non-heap objects
- A local variable to a method on the stack
- An input parameter to a method on the stack
- The return value of the method on the stack
- NULL pointer
Use of compressed Pointers
Starting with Oracle JDK1.8, 64-bit JVMS have compressed Pointers enabled by default. If you want to manually adjust them, see the following configuration
# Enable pointer compression (default) -xx :+UseCompressedOops # Disable pointer compression -xx: -usecompressedoopsCopy the code
Compressed pointer failure
-
If the heap size is less than 4G: the compression pointer is not used and the JVM uses a low virutal address space (64-bit emulates 32-bit) to avoid the CPU performance cost of compression and decompression operations
-
If the heap size is greater than 4 gb and less than 32 GB: enable CompressedOop
-
If the heap size is greater than 32GB: Since the compression pointer can only represent a maximum of 32GB of heap memory, the compression pointer cannot use more than 32GB of memory. Therefore, CompressedOop is not enabled when the heap size is greater than 32GB
As a rule of thumb, 40GB of heap memory can store about the same number of objects as 32GB of heap memory
32GB is a theoretical value, but in practice, compression pointer failure may occur at more than 31GB
reference
CompressedOops
The hotspot source