Object Layout
Java object layout¶
Provides a good guide to the size of the object header in Java and what it is made up of, for 64bit (compressed oops on and off) and 32 bit JVM.
https://gist.github.com/arturmkrtchyan/43d6135e8a15798cc46c
Excellent guide to memory layout: http://psy-lob-saw.blogspot.com/2013/05/know-thy-java-object-memory-layout.html
Rules¶
(Taken from psy-lob-saw>)
- Objects are aligned on 8 byte boundary
- Fields are also type aligned, long = 8 byte, int = 4 byte, short/char = 2 byte
- Fields are packed in the order of their size, except for references which are last
The tool jol is a library that can be used to identify the expected size of an object.
Here we see the output for testing with jol on a 64bit compressed oops JVM.
public final class MyClassSingleInt {
public int value;
}
com.bvb.MyClassSingleInt object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 12 (object header) N/A
12 4 int MyClassSingleInt.value N/A
Instance size: 16 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total
public final class MyClassTwoInts {
public int int1;
public int int2;
}
com.bvb.MyClassTwoInts object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 12 (object header) N/A
12 4 int MyClassTwoInts.int1 N/A
16 4 int MyClassTwoInts.int2 N/A
20 4 (loss due to the next object alignment)
Instance size: 24 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
You can see that the second object with two ints, each of size 4 bytes, will lose a total of 4 bytes due to the alignment of the object on 8 byte boundaries.
Object header¶
See the link above for 32bit, not used that often at this point.
64bit compressed OOP¶
Mark word is always as wide as the full reference without compressed OOP. But the Klass word can be OOP.
|--------------------------------------------------------------------------------------------------------------|--------------------|
| Object Header (96 bits) | State |
|--------------------------------------------------------------------------------|-----------------------------|--------------------|
| Mark Word (64 bits) | Klass Word (32 bits) | |
|--------------------------------------------------------------------------------|-----------------------------|--------------------|
| unused:25 | identity_hashcode:31 | cms_free:1 | age:4 | biased_lock:1 | lock:2 | OOP to metadata object | Normal |
|--------------------------------------------------------------------------------|-----------------------------|--------------------|
| thread:54 | epoch:2 | cms_free:1 | age:4 | biased_lock:1 | lock:2 | OOP to metadata object | Biased |
|--------------------------------------------------------------------------------|-----------------------------|--------------------|
| ptr_to_lock_record | lock:2 | OOP to metadata object | Lightweight Locked |
|--------------------------------------------------------------------------------|-----------------------------|--------------------|
| ptr_to_heavyweight_monitor | lock:2 | OOP to metadata object | Heavyweight Locked |
|--------------------------------------------------------------------------------|-----------------------------|--------------------|
| | lock:2 | OOP to metadata object | Marked for GC |
|--------------------------------------------------------------------------------|-----------------------------|--------------------|
64bit¶
|------------------------------------------------------------------------------------------------------------|--------------------|
| Object Header (128 bits) | State |
|------------------------------------------------------------------------------|-----------------------------|--------------------|
| Mark Word (64 bits) | Klass Word (64 bits) | |
|------------------------------------------------------------------------------|-----------------------------|--------------------|
| unused:25 | identity_hashcode:31 | unused:1 | age:4 | biased_lock:1 | lock:2 | OOP to metadata object | Normal |
|------------------------------------------------------------------------------|-----------------------------|--------------------|
| thread:54 | epoch:2 | unused:1 | age:4 | biased_lock:1 | lock:2 | OOP to metadata object | Biased |
|------------------------------------------------------------------------------|-----------------------------|--------------------|
| ptr_to_lock_record:62 | lock:2 | OOP to metadata object | Lightweight Locked |
|------------------------------------------------------------------------------|-----------------------------|--------------------|
| ptr_to_heavyweight_monitor:62 | lock:2 | OOP to metadata object | Heavyweight Locked |
|------------------------------------------------------------------------------|-----------------------------|--------------------|
| | lock:2 | OOP to metadata object | Marked for GC |
|------------------------------------------------------------------------------|-----------------------------|--------------------|
Klass word¶
- The class word contains a pointer to the native memory representation of the class.
- Link to Klass from j11: https://hg.openjdk.java.net/jdk/jdk11/file/1ddf9a99e4ad/src/hotspot/share/oops/klass.hpp
- Because of the compressed ordinary object pointers, we have a shorthand reference to the native memory location. See the following for more info: https://stuefe.de/posts/metaspace/what-is-compressed-class-space/