java对象头的大小_对象头所占空间大小以及对象头存储内容?

两种说法中对象头涵盖的内容不同,前者所指的Object Header仅仅指的是markOop指针的大小——在32位机器上指针的大小是32bit(4Bytes),在64位机器上指针的大小是64bit(8Bytes);而后者除了markOop指针之外,还包含了Klass*这一个类型元数据,用于描述Heap对象在Metaspace中的实际类型,那么在不考虑启用压缩指针: -XX:+UseCompressedOops的情况下,加上这个Klass*指针的大小,Object Header在32位VM里占64bit内存空间,在64位VM里占128位内存空间的结论。在启用压缩指针之后,64位VM的Klass*指针会被压缩成narrowKlass -> unsigned int类型的大小——变成了32bit,因为是union类型,所以_metadata还是占用了64bit的内存空间,多出来的32bit空间就空着了——后面会讲到它的用处。我更倾向于将普通对象的对象头定义为【markOop + Klass*】的组合,所以后者的结论可能更合适。

基于此,在HotSpot VM中,普通对象的对象头是这么定义的:

volatile markOop _mark;

union _metadata {

Klass* _klass;

narrowKlass _compressed_klass;

} _metadata;

对于数组这种特殊的对象,它的对象头中又增加了一个length用于描述数组的大小,在HotSpot VM中如果启用压缩指针的话,它其实是占用的_metadata空出来的后面的4个字节的内存空间,因此这种情况下128bit的内容空间就能表示一个数组的对象头了;如果没有启用指针压缩 -XX:-UseCompressedOops呢?它会追加到内嵌的实例数据的最后,这时候考虑到字节对齐,我们无法给出确切的大小了。

// The layout of array Oops is:

//

// markOop

// Klass* // 32 bits if compressed but declared 64 in LP64.

// length // shares klass memory or allocated after declared fields.

markOop用于存储对象在runtime是的有用信息,如哈希码(HashCode)、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳、转发指针等等。VM使用这些紧凑的bitMap描述对象在同步过程或GC过程中的的必要信息,辅助VM Runtime实现对象的同步机制和垃圾回收的功能——虽然看到R大有时候吐槽这玩意儿尤其是RT的同步机制开销很大~

回到题主的问题,对象头中是否存储了类型的地址信息——答案见上面,这就是所谓的Klass*。至于JavaThread*线程所有者的指针大小,请看下面的注释——在HotSpot VM中 Thread在new的时候已经采用了一定的算法,将它的指针大小控制在了譬如32位VM下仅占用23bit的内存空间——所以,请放心,放得下。

// The markOop describes the header of an object.

//

// Note that the mark is not a real oop but just a word.

// It is placed in the oop hierarchy for historical reasons.

//

// Bit-format of an object header (most significant first, big endian layout below):

//

// 32 bits:

// --------

// hash:25 ------------>| age:4 biased_lock:1 lock:2 (normal object)

// JavaThread*:23 epoch:2 age:4 biased_lock:1 lock:2 (biased object)

// size:32 ------------------------------------------>| (CMS free block)

// PromotedObject*:29 ---------->| promo_bits:3 ----->| (CMS promoted object)

//

// 64 bits:

// --------

// unused:25 hash:31 -->| unused:1 age:4 biased_lock:1 lock:2 (normal object)

// JavaThread*:54 epoch:2 unused:1 age:4 biased_lock:1 lock:2 (biased object)

// PromotedObject*:61 --------------------->| promo_bits:3 ----->| (CMS promoted object)

// size:64 ----------------------------------------------------->| (CMS free block)

//

// unused:25 hash:31 -->| cms_free:1 age:4 biased_lock:1 lock:2 (COOPs && normal object)

// JavaThread*:54 epoch:2 cms_free:1 age:4 biased_lock:1 lock:2 (COOPs && biased object)

// narrowOop:32 unused:24 cms_free:1 unused:4 promo_bits:3 ----->| (COOPs && CMS promoted object)

// unused:21 size:35 -->| cms_free:1 unused:7 ------------------>| (COOPs && CMS free block)

//

// - hash contains the identity hash value: largest value is

// 31 bits, see os::random(). Also, 64-bit vm's require

// a hash value no bigger than 32 bits because they will not

// properly generate a mask larger than that: see library_call.cpp

// and c1_CodePatterns_sparc.cpp.

//

// - the biased lock pattern is used to bias a lock toward a given

// thread. When this pattern is set in the low three bits, the lock

// is either biased toward a given thread or "anonymously" biased,

// indicating that it is possible for it to be biased. When the

// lock is biased toward a given thread, locking and unlocking can

// be performed by that thread without using atomic operations.

// When a lock's bias is revoked, it reverts back to the normal

// locking scheme described below.

//

// Note that we are overloading the meaning of the "unlocked" state

// of the header. Because we steal a bit from the age we can

// guarantee that the bias pattern will never be seen for a truly

// unlocked object.

//

// Note also that the biased state contains the age bits normally

// contained in the object header. Large increases in scavenge

// times were seen when these bits were absent and an arbitrary age

// assigned to all biased objects, because they tended to consume a

// significant fraction of the eden semispaces and were not

// promoted promptly, causing an increase in the amount of copying

// performed. The runtime system aligns all JavaThread* pointers to

// a very large value (currently 128 bytes (32bVM) or 256 bytes (64bVM))

// to make room for the age bits & the epoch bits (used in support of

// biased locking), and for the CMS "freeness" bit in the 64bVM (+COOPs).

//

// [JavaThread* | epoch | age | 1 | 01] lock is biased toward given thread

// [0 | epoch | age | 1 | 01] lock is anonymously biased

//

// - the two lock bits are used to describe three states: locked/unlocked and monitor.

//

// [ptr | 00] locked ptr points to real header on stack

// [header | 0 | 01] unlocked regular object header

// [ptr | 10] monitor inflated lock (header is wapped out)

// [ptr | 11] marked used by markSweep to mark an object

// not valid at any other time

//

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值