JAVA 对象头MarkWord
最近在并发编程的学习中,接触到了JAVA对象头中的MarkWord. 在此做下笔记,也和小伙伴们分享一下,共同进步!
MarkWord介绍
MarkWord是Java对象存储在内存中的一部分信息.
在32位系统中使用32位存储, 64位系统中使用64存储.以下是来自Hotspot中源码注释!
HotSpot源码注释中给出的是大端存储下的Layout.
我们平时电脑都是小端存储的,所以后续的测试结果中会出现和下图不匹配的情况!
关于大小端存储可以参考下图
HotSpot源码注释
// 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)
64位系统中,MarkWord结构如下
学习对象头,我们需要依赖一个工具JOL (JAVA OBJECT LAYOUT)可以通过pom.xml进行引入
<dependency>
<groupId>org.openjdk.jol</groupId>
<artifactId>jol-core</artifactId>
<version>0.14</version>
<scope>provided</scope>
</dependency>
001 无锁,不可偏向状态
@Test
public void testUnLock() throws InterruptedException {
System.out.println("第一次结果: ");
System.out.println(ClassLayout.parseInstance(new Object()).toPrintable());
Thread.sleep(4000);
System.out.println("第二次结果: ");
System.out.println(ClassLayout.parseInstance(new Object()).toPrintable());
}
101 无锁,可偏向状态
@Test
public void testBiasedUnLock() throws InterruptedException {
// 关闭延迟开启偏向锁
// -XX:BiasedLockingStartupDelay=0
Object o = new Object();
System.out.println("第一次结果: ");
System.out.println(ClassLayout.parseInstance(o).toPrintable());
int hashCode = o.hashCode();
System.out.println("第二次结果: ");
System.out.println(ClassLayout.parseInstance(o).toPrintable());
}
101 偏向锁
static final Object lock = new Object();
@Test
public void testBiasedLock() {
// 关闭延迟开启偏向锁
// -XX:BiasedLockingStartupDelay=0
System.out.println("第一次结果: ");
System.out.println(ClassLayout.parseInstance(lock).toPrintable());
synchronized (lock){
System.out.println("加锁后结果: ");
System.out.println(ClassLayout.parseInstance(lock).toPrintable());
}
System.out.println("解锁后结果: ");
System.out.println(ClassLayout.parseInstance(lock).toPrintable());
}
00 轻量锁
static final Object lock = new Object();
@Test
public void testLock() {
// 关闭延迟开启偏向锁
// -XX:BiasedLockingStartupDelay=0
synchronized (lock){
System.out.println("主线程加锁: ");
System.out.println(ClassLayout.parseInstance(lock).toPrintable());
}
new Thread(()->{
synchronized (lock){
System.out.println("子线程加锁: ");
System.out.println(ClassLayout.parseInstance(lock).toPrintable());
}
}).start();
}
10 重量锁
static final Object lock = new Object();
@Test
public void testInflatedLock() throws InterruptedException {
Thread t1 = new Thread(() -> {
synchronized (lock) {
System.out.println("t1加锁: ");
System.out.println(ClassLayout.parseInstance(lock).toPrintable());
}
});
Thread t2 = new Thread(() -> {
synchronized (lock) {
System.out.println("t2加锁: ");
System.out.println(ClassLayout.parseInstance(lock).toPrintable());
}
});
t1.start();
t2.start();
// 等待t1, t2执行完, 否则无法打印
t1.join();
t2.join();
}
11 GC标记清除
由于标记清除是指此对象已被垃圾回收器标记成可回收对象.所以演示不出来.