When tuning the JVM memory, we inevitably need to calculate the size of the object. To calculate the size of an object, it is necessary to consider whether it is an ordinary object or an array object, because the object headers of ordinary objects and array objects are slightly different. And since JDK6, in order to save memory and improve operating efficiency, a new technology has been introduced: pointer compression. It further increases the difficulty of calculating the size of the object.
This article will in-depth analyze how to calculate the object size to ensure that the calculated result is not one byte different from the actual situation.
Object structure
The object structure must be known to anyone who has studied JVM in depth. It is divided into three parts: object header, instance data, and alignment padding. The object header is divided into three parts: Mark Word, type pointer, and array length. In fact, there is a fourth part of the object header, which is not mentioned in the books and videos you have seen so far. The object header also has an alignment and padding part. This part is not necessarily there. Only the array object does not have pointer compression enabled. Appears below. If you are confused, then continue to look back.
Pointer compression
Seeing these four words is there a bunch of question marks: What is this? How is this achieved? Why does it save memory? ... Let's clarify these issues.
Let's first reach a conceptual agreement: all objects are aligned with 8 bytes. Now I have 3 objects: test1 (16 bytes), test2 (32 bytes), test3 (24 bytes). For the sake of explanation, if there are no other objects among these three objects, their memory addresses are:
test1 = 0x0000 0 000(0字节 ~ 16字节)
test2 = 0x0001 0 000(16字节 ~ 48字节)
test3 = 0x0011 0 000(48字节 ~ 72字节)
Have you discovered the law? The last three bits of all object pointers are 0. This is the principle of pointer compression. After the pointer compression is turned on, the JVM will cut off the last three digits of the object pointer. If test2 = 0x10000, it will become test2=0x10 after the pointer is turned on. When using it, the last three digits of 0 will be added back, that is, test2 =0x10 000.
Because after the pointer compression is turned on, the object pointer becomes 4 bytes (32 bits), plus 3 bits, for a total of 35 bits. That is, the maximum heap space that can be represented by an object pointer after pointer compression is turned on is 2 to the 35th power, which is 32G.
Can the reader think about it? What if I want to expand the size of the heap space that an oop can represent?
Let's look at how the object size is calculated in four situations (normal object-pointer compression turned off, ordinary object-pointer compression turned on, array object-pointer compression turned off, and array object-pointer compression turned on). It is recommended that readers write similar code to test it, so as to have a deeper understanding.
Test code:
package com.qimingnan.adjust;
import org.openjdk.jol.info.ClassLayout;
public class Test1 {
int a = 10;
int b = 20;
static int[] arr = {0, 1, 2};
public static void main(String[] args) {
Test1 test1 = new Test1();
System.out.printf(ClassLayout.parseInstance(test1).toPrintable());
System.out.printf(ClassLayout.parseInstance(arr).toPrintable());
}
}
Ordinary object
1. Pointer compression is not turned on
24B = 8B(Mark Word)+ 8B(KClass Pointer)+ 4B + 4B
2. Turn on pointer compression
24B = 8B(Mark Word)+ 4B(KClass Pointer)+ 4B(int a)+ 4B(int b)+ 4B(Padding)
Array object
1. Pointer compression is not turned on
40B = 8B (Mark Word) + 8B (KClass Pointer) + 4B (array length) + 4B (head padding) + 12B (3 int) + 4B (object padding)
2. Turn on pointer compression
32B = 8B (Mark Word) + 4B (KClass Pointer) + 4B (array length) + 12B (3 ints) + 4B (object padding)
Have you learned how to calculate the size of an object?
Introduce a tool, jol, everyone can use this tool when doing tests
<dependency>
<groupId>org.openjdk.jol</groupId>
<artifactId>jol-core</artifactId>
<version>0.10</version>
</dependency>
Some parts of this article may not be easy to understand. If readers have questions, leave a message and ask questions. I will reply one by one.
I will open a new column of "Handwritten JVM" for you in the follow-up. If you are interested in this, then follow me.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。