JOL 16 Identity Hash Code 和 Biased Locking 冲突


本篇文章基于V0.16 JOLSample_16_IHC_BL_Conflict

这个例子用于演示当偏向锁遇到hash code时发生的冲突。实验证明hash code拥有更高的优先级.

第一次释放锁之后,mark word并没有发生变化还是处于偏向锁状态。当我们计算了hash code之后,hash code值会覆盖之前的偏向锁的值。当第二次进入锁之后,mark word被重新赋值了偏向锁引用,但是离开锁之后,mark word 并没有保留偏向锁引用,而是重新被赋值了hash code。因此我们可以看出,在mark word中hash code比偏向锁拥有更高的优先级。

在JDK 15+以上,测试代码需要开启-XX:+UseBiasedLocking参数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
public class JOLSample_16_IHC_BL_Conflict {

public static void main(String[] args) throws Exception {
out.println(VM.current().details());

TimeUnit.SECONDS.sleep(6);

final A a = new A();

ClassLayout layout = ClassLayout.parseInstance(a);

out.println("**** Fresh object");
out.println(layout.toPrintable());

synchronized (a) {
out.println("**** With the lock");
out.println(layout.toPrintable());
}

out.println("**** After the lock");
out.println(layout.toPrintable());

int hashCode = a.hashCode();
out.println("hashCode: " + Integer.toHexString(hashCode));
out.println();

out.println("**** After the hashcode");
out.println(layout.toPrintable());

synchronized (a) {
out.println("**** With the second lock");
out.println(layout.toPrintable());
}

out.println("**** After the second lock");
out.println(layout.toPrintable());
}

public static class A {
// no fields
}

}

运行结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# Running 64-bit HotSpot VM.
# Using compressed oop with 3-bit shift.
# Using compressed klass with 3-bit shift.
# WARNING | Compressed references base/shifts are guessed by the experiment!
# WARNING | Therefore, computed addresses are just guesses, and ARE NOT RELIABLE.
# WARNING | Make sure to attach Serviceability Agent to get the reliable addresses.
# Objects are 8 bytes aligned.
# Field sizes by type: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]
# Array element sizes: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]

**** Fresh object
org.openjdk.jol.samples.JOLSample_16_IHC_BL_Conflict$A object internals:
OFF SZ TYPE DESCRIPTION VALUE
0 8 (object header: mark) 0x0000000000000005 (biasable; age: 0)
8 4 (object header: class) 0xf80121fa
12 4 (object alignment gap)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

**** With the lock
org.openjdk.jol.samples.JOLSample_16_IHC_BL_Conflict$A object internals:
OFF SZ TYPE DESCRIPTION VALUE
0 8 (object header: mark) 0x00007fbe92009005 (biased: 0x0000001fefa48024; epoch: 0; age: 0)
8 4 (object header: class) 0xf80121fa
12 4 (object alignment gap)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

**** After the lock
org.openjdk.jol.samples.JOLSample_16_IHC_BL_Conflict$A object internals:
OFF SZ TYPE DESCRIPTION VALUE
0 8 (object header: mark) 0x00007fbe92009005 (biased: 0x0000001fefa48024; epoch: 0; age: 0)
8 4 (object header: class) 0xf80121fa
12 4 (object alignment gap)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

hashCode: 6073f712

**** After the hashcode
org.openjdk.jol.samples.JOLSample_16_IHC_BL_Conflict$A object internals:
OFF SZ TYPE DESCRIPTION VALUE
0 8 (object header: mark) 0x0000006073f71201 (hash: 0x6073f712; age: 0)
8 4 (object header: class) 0xf80121fa
12 4 (object alignment gap)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

**** With the second lock
org.openjdk.jol.samples.JOLSample_16_IHC_BL_Conflict$A object internals:
OFF SZ TYPE DESCRIPTION VALUE
0 8 (object header: mark) 0x00007000089b39e0 (thin lock: 0x00007000089b39e0)
8 4 (object header: class) 0xf80121fa
12 4 (object alignment gap)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

**** After the second lock
org.openjdk.jol.samples.JOLSample_16_IHC_BL_Conflict$A object internals:
OFF SZ TYPE DESCRIPTION VALUE
0 8 (object header: mark) 0x0000006073f71201 (hash: 0x6073f712; age: 0)
8 4 (object header: class) 0xf80121fa
12 4 (object alignment gap)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total