Java object header

Have you ever wondered how java object looks like inside JVM ?
First, remember that in jvm any object in memory consists of the object header and object variables (links and primitives).
The header of each object (except for the array) consists of two machine words - mark word and class word . Arrays have an additional 32 bits to describe the length of the array.
Mark word stores identity hashcode, bits used by the garbage collector and bits used for locks.
In Class word, a pointer is stored to the class itself, that is, to the place where the information about this data type lies: methods, annotations, inheritance, and more.

Let’s now take a closer look at the title of the object, and in particular the mark word.

What about 32 bit JVM?

在这里插入图片描述
As can be seen from the table, the content of Mark word can vary greatly depending on the current state of the object.

  • identity_hashcode - identity hashcode of the object which is assigned lazily. If System.identityHashCode(obj) is called, it is calculated and written into the object header. When object is locked the identity hashcode value is moved into the monitor object.
  • age - number of garbage collections the object has survived. It is incremented every time an object is copied within the young generation. When the age field reaches the value of max-tenuring-threshold, the object is promoted to the old generation.
  • biased_lock - contains 1 if the biased locking is enabled for the class. 0 if the biased locking is disabled for the class. To find out more on biased locking check out my previous post.
  • lock - the lock state of the object. 00 - Lightweight Locked, 01 - Unlocked or Biased, 10 - Heavyweight Locked, 11 - Marked for Garbage Collection.
  • thread - when an object is biased towards specific thread instead of identity hash code mark word contains thread id.
  • epoch - which acts as a timestamp that indicates the validity of the bias.
  • ptr_to_lock_record - When lock acquisitions are uncontended JVM uses atomic operations instead of OS mutexes. This technique is known as Lightweight Locking. In case of lightweight locking JVM sets a pointer to the lock record in the object’s header word via a CAS operation.
  • ptr_to_heavyweight_monitor - If two different threads concurrently synchronize on the same object, the lightweight lock must be inflated to a Heavyweight Monitor for the management of waiting threads. In case of heavyweight locking JVM sets a pointer to the monitor in the object’s header word.
What about 64 bit JVM?

在这里插入图片描述

What about 64 bit JVM with pointer compression?

在这里插入图片描述
Let’s talk a bit about Ordinary Object Pointers (OOPs) and Compressed OOPs (Coops). OOPs are the handles/pointers the JVM uses as object references. When oops are only 32 bits long, they can reference only 4 GB of memory, which is why a 32-bit JVM is limited to a 4 GB heap size. (The same restriction applies at the operating system level, which is why any 32-bit process is limited to 4GB of address space.) When oops are 64 bits long, they can reference terabytes of memory.
What if there were 35-bit oops? Then the pointer could reference 32 GB of memory and still take up less space in the heap than 64-bit references. The problem is that there aren’t 35-bit registers in which to store such references. Instead, though, the JVM can assume that the last 3 bits of the reference are all 0. Now every reference can be stored in 32 bits in the heap. When the reference is stored into a 64-bit register, the JVM can shift it left by 3 bits (adding three zeros at the end). When the reference is saved from a register, the JVM can right-shift it by 3 bits, discarding the zeros at the end.
This allows JVM to use pointers that can reference 32 GB of memory while using only 32 bits in the heap. However it also means that the JVM cannot access any object at an address that isn’t divisible by 8, since any address from a compressed oop ends with three zeros. The first possible oop is 0x1, which when shifted becomes 0x8. The next oop is 0x2, which when shifted becomes 0x10 (16). Objects must therefore be located on an 8-byte boundary. As we know objects are already aligned on an 8-byte boundary in the JVM (in both the 32- and 64-bit versions); this is the optimal alignment for most processors. So nothing is lost by using compressed oops.
A program that uses a 31 GB heap and compressed oops will usually be faster than a program that uses a 33 GB heap. Although the 33 GB heap is larger, the extra space used by the pointers in that heap means that the larger heap will perform more frequent GC cycles and have worse performance.
Compressed oops are enabled using the -XX:+UseCompressedOops flag; in Java 7 and later versions, they are enabled by default whenever the maximum heap size is less than 32 GB.

参考:
《Java object header》
《Java object header》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值