盘锦做网站价格/深圳百度seo优化
前言
09 给对象添加偏向锁的调试
10 偏向锁的退出的调试
呵呵 接着前两篇
本文调试一下 一下的几个场景
1. 偏向锁的重入
2. 线程1添加了偏向锁并释放, 线程2来获取锁
一下内容基于 jdk9 + lldb-1001.0.13.3
另外一下 运行时数据可能是来自于多次调试, 可能会存在运行时数据 对不上的情况, 但是的条理逻辑会在文字中描述清楚的
偏向锁重入的测试用例
package com.hx.test04;/*** Test26SynchronizeReentrantObject** @author Jerry.X.He <970655147@qq.com>* @version 1.0* @date 2020-04-03 15:14*/
public class Test26SynchronizeReentrantObject implements Cloneable {// identStrprivate String identStr = "xyz";int f01;int f02;int f03;int f04;int f05;// Test26SynchronizeReentrantObjectpublic static void main(String[] args) throws Exception {Test26SynchronizeReentrantObject lockObj = new Test26SynchronizeReentrantObject();synchronized (lockObj) {synchronized (lockObj) {// Test26SynchronizeReentrantObject cloned = (Test26SynchronizeReentrantObject) lockObj.clone();
// System.out.println(lockObj.identStr);}}}}
对应的字节码信息如下, 下面参照可能需要使用到
master:classes jerry$ javap -c com/hx/test04/Test26SynchronizeReentrantObject.class
Compiled from "Test26SynchronizeReentrantObject.java"
public class com.hx.test04.Test26SynchronizeReentrantObject implements java.lang.Cloneable {int f01;int f02;int f03;int f04;int f05;public com.hx.test04.Test26SynchronizeReentrantObject();Code:0: aload_01: invokespecial #1 // Method java/lang/Object."<init>":()V4: aload_05: ldc #2 // String xyz7: putfield #3 // Field identStr:Ljava/lang/String;10: returnpublic static void main(java.lang.String[]) throws java.lang.Exception;Code:0: new #4 // class com/hx/test04/Test26SynchronizeReentrantObject3: dup4: invokespecial #5 // Method "<init>":()V7: astore_18: aload_19: dup10: astore_211: monitorenter12: aload_113: dup14: astore_315: monitorenter16: aload_317: monitorexit18: goto 2821: astore 423: aload_324: monitorexit25: aload 427: athrow28: aload_229: monitorexit30: goto 4033: astore 535: aload_236: monitorexit37: aload 539: athrow40: returnException table:from to target type16 18 21 any21 25 21 any12 30 33 any33 37 33 any
}
进入lldb的调试
同样的配方同样的味道, 这里就不在输出 一些 定位一下当前方法 的日志了, 直接进入 正题
(lldb) p _active_table._table[9][194]
(address) $0 = 0x000000010524f980 "XH;"
(lldb) b 0x000000010524f980
Breakpoint 3: address = 0x000000010524f980
(lldb) c
Process 2762 resuming
Process 2762 stopped
* thread #5, stop reason = breakpoint 3.1frame #0: 0x000000010524f980
-> 0x10524f980: popq %rax0x10524f981: cmpq (%rax), %rax0x10524f984: xorl %esi, %esi0x10524f986: movq -0x48(%rbp), %rcx
Target 0: (java) stopped.
(lldb) re r
General Purpose Registers:rax = 0x0000000747bb8798rbx = 0x00000000000000c2rcx = 0x0000000000000008rdx = 0x0000000747bb87b8rdi = 0x0000000101806000rsi = 0x000070000ba375c0rbp = 0x000070000ba37670rsp = 0x000070000ba37620r8 = 0x0000000000000000r9 = 0x0000000000000020r10 = 0x0000000104b0b270 libjvm.dylib`TemplateInterpreter::_active_table + 18432r11 = 0x00006fff0a229200r12 = 0x0000000000000000r13 = 0x000000011d1eff93r14 = 0x000070000ba376a8r15 = 0x0000000101806000rip = 0x000000010524f980rflags = 0x0000000000000206cs = 0x000000000000002bfs = 0x0000000000000000gs = 0x0000000000000000(lldb) p ((oopDesc*)0x0000000747bb8798)->print()
com.hx.test04.Test26SynchronizeReentrantObject
{0x0000000747bb8798} - klass: 'com/hx/test04/Test26SynchronizeReentrantObject'- ---- fields (total size 5 words):- 'f01' 'I' @12 0- 'f02' 'I' @16 0- 'f03' 'I' @20 0- 'f04' 'I' @24 0- 'f05' 'I' @28 0- private 'identStr' 'Ljava/lang/String;' @32 "xyz"{0x0000000747bb87c0} (e8f770f8 0)
(lldb) x 0x0000000747bb8798
0x747bb8798: 05 00 00 00 00 00 00 00 86 1f 01 f8 00 00 00 00 ...........?....
0x747bb87a8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
(lldb) x 0x000070000ba37620 -c 0x100
0x70000ba37620: 98 87 bb 47 07 00 00 00 28 76 a3 0b 00 70 00 00 ..?G....(v?..p..
0x70000ba37630: 8c ff 1e 1d 01 00 00 00 a8 76 a3 0b 00 70 00 00 .?......?v?..p..
0x70000ba37640: 88 00 1f 1d 01 00 00 00 00 00 00 00 00 00 00 00 ................
0x70000ba37650: 70 82 bb 47 07 00 00 00 00 00 1f 1d 01 00 00 00 p.?G............
0x70000ba37660: 00 00 00 00 00 00 00 00 a8 76 a3 0b 00 70 00 00 ........?v?..p..
0x70000ba37670: 10 77 a3 0b 00 70 00 00 f1 09 20 05 01 00 00 00 .w?..p..?. .....
0x70000ba37680: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x70000ba37690: 00 00 00 00 00 00 00 00 98 87 bb 47 07 00 00 00 ..........?G....
0x70000ba376a0: 98 87 bb 47 07 00 00 00 88 87 bb 47 07 00 00 00 ..?G......?G....
0x70000ba376b0: a0 1f 00 00 03 00 00 00 00 00 00 00 00 00 00 00 ?...............
0x70000ba376c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x70000ba376d0: 00 00 00 00 00 00 00 00 00 80 a3 0b 00 70 00 00 ..........?..p..
0x70000ba376e0: 20 78 a3 0b 00 70 00 00 50 7d a3 0b 00 70 00 00 x?..p..P}?..p..
0x70000ba376f0: 0a 00 00 00 00 70 00 00 00 00 1f 1d 01 00 00 00 .....p..........
0x70000ba37700: 00 a7 22 05 01 00 00 00 a0 7a a3 0b 00 70 00 00 .?".....?z?..p..
0x70000ba37710: e0 78 a3 0b 00 70 00 00 1d bb 0e 04 01 00 00 00 ?x?..p...?......// continue, 之后 断点停留在了 第二个 monitorenter
(lldb) c
Process 2762 resuming
Process 2762 stopped
* thread #5, stop reason = breakpoint 3.1frame #0: 0x000000010524f980
-> 0x10524f980: popq %rax0x10524f981: cmpq (%rax), %rax0x10524f984: xorl %esi, %esi0x10524f986: movq -0x48(%rbp), %rcx
Target 0: (java) stopped.
(lldb) p ((oopDesc*)0x0000000747bb8798)->print()
com.hx.test04.Test26SynchronizeReentrantObject
{0x0000000747bb8798} - klass: 'com/hx/test04/Test26SynchronizeReentrantObject'- ---- fields (total size 5 words):- 'f01' 'I' @12 0- 'f02' 'I' @16 0- 'f03' 'I' @20 0- 'f04' 'I' @24 0- 'f05' 'I' @28 0- private 'identStr' 'Ljava/lang/String;' @32 "xyz"{0x0000000747bb87c0} (e8f770f8 0)
(lldb) p ((oopDesc*)0x0000000747bb8798)->mark()->biased_locker()->threadObj()->print()
java.lang.Thread
{0x0000000747f069d8} - klass: 'java/lang/Thread'- ---- fields (total size 47 words):- private 'priority' 'I' @12 5- private 'eetop' 'J' @16 4320157696 (1806000 1)- private 'stackSize' 'J' @24 0 (0 0)- private 'nativeParkEventPointer' 'J' @32 0 (0 0)- private 'tid' 'J' @40 1 (1 0)- private volatile 'threadStatus' 'I' @48 5- private 'single_step' 'Z' @52 false- private 'daemon' 'Z' @53 false- private 'stillborn' 'Z' @54 false- private volatile 'name' 'Ljava/lang/String;' @56 "main"{0x0000000747f06b50} (e8fe0d6a 0)- private 'threadQ' 'Ljava/lang/Thread;' @60 NULL (0 0)- private 'target' 'Ljava/lang/Runnable;' @64 NULL (0 e8fe0c85)- private 'group' 'Ljava/lang/ThreadGroup;' @68 a 'java/lang/ThreadGroup'{0x0000000747f06428} (e8fe0c85 e8fc0af7)- private 'contextClassLoader' 'Ljava/lang/ClassLoader;' @72 a 'jdk/internal/loader/ClassLoaders$AppClassLoader'{0x0000000747e057b8} (e8fc0af7 e8fe0d91)- private 'inheritedAccessControlContext' 'Ljava/security/AccessControlContext;' @76 a 'java/security/AccessControlContext'{0x0000000747f06c88} (e8fe0d91 e8fe2fb8)- 'threadLocals' 'Ljava/lang/ThreadLocal$ThreadLocalMap;' @80 a 'java/lang/ThreadLocal$ThreadLocalMap'{0x0000000747f17dc0} (e8fe2fb8 0)- 'inheritableThreadLocals' 'Ljava/lang/ThreadLocal$ThreadLocalMap;' @84 NULL (0 0)- volatile 'parkBlocker' 'Ljava/lang/Object;' @88 NULL (0 0)- private volatile 'blocker' 'Lsun/nio/ch/Interruptible;' @92 NULL (0 e8fe0d70)- private final 'blockerLock' 'Ljava/lang/Object;' @96 a 'java/lang/Object'{0x0000000747f06b80} (e8fe0d70 0)- private volatile 'uncaughtExceptionHandler' 'Ljava/lang/Thread$UncaughtExceptionHandler;' @100 NULL (0 0)- 'threadLocalRandomSeed' 'J' @232 0 (0 0)- 'threadLocalRandomProbe' 'I' @240 0- 'threadLocalRandomSecondarySeed' 'I' @244 0
(lldb) x 0x0000000747bb8798
0x747bb8798: 05 60 80 01 01 00 00 00 86 1f 01 f8 00 00 00 00 .`.........?....
0x747bb87a8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
(lldb) re r
General Purpose Registers:rax = 0x0000000747bb8798rbx = 0x00000000000000c2rcx = 0x0000000747bb8798rdx = 0x000070000ba37628rdi = 0x0000000101806000rsi = 0x000070000ba37618rbp = 0x000070000ba37670rsp = 0x000070000ba37610r8 = 0x0000000000000000r9 = 0x0000000000000020r10 = 0x0000000104b0b270 libjvm.dylib`TemplateInterpreter::_active_table + 18432r11 = 0x00006fff0a229200r12 = 0x0000000000000000r13 = 0x000000011d1eff97r14 = 0x000070000ba376a8r15 = 0x0000000101806000rip = 0x000000010524f980rflags = 0x0000000000000202cs = 0x000000000000002bfs = 0x0000000000000000gs = 0x0000000000000000
(lldb) x 0x000070000ba37610 -c 0x100
0x70000ba37610: 98 87 bb 47 07 00 00 00 98 87 bb 47 07 00 00 00 ..?G......?G....
0x70000ba37620: 98 87 bb 47 07 00 00 00 18 76 a3 0b 00 70 00 00 ..?G.....v?..p..
0x70000ba37630: 94 ff 1e 1d 01 00 00 00 a8 76 a3 0b 00 70 00 00 .?......?v?..p..
0x70000ba37640: 88 00 1f 1d 01 00 00 00 00 00 00 00 00 00 00 00 ................
0x70000ba37650: 70 82 bb 47 07 00 00 00 00 00 1f 1d 01 00 00 00 p.?G............
0x70000ba37660: 00 00 00 00 00 00 00 00 a8 76 a3 0b 00 70 00 00 ........?v?..p..
0x70000ba37670: 10 77 a3 0b 00 70 00 00 f1 09 20 05 01 00 00 00 .w?..p..?. .....
0x70000ba37680: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x70000ba37690: 98 87 bb 47 07 00 00 00 98 87 bb 47 07 00 00 00 ..?G......?G....
0x70000ba376a0: 98 87 bb 47 07 00 00 00 88 87 bb 47 07 00 00 00 ..?G......?G....
0x70000ba376b0: a0 1f 00 00 03 00 00 00 00 00 00 00 00 00 00 00 ?...............
0x70000ba376c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x70000ba376d0: 00 00 00 00 00 00 00 00 00 80 a3 0b 00 70 00 00 ..........?..p..
0x70000ba376e0: 20 78 a3 0b 00 70 00 00 50 7d a3 0b 00 70 00 00 x?..p..P}?..p..
0x70000ba376f0: 0a 00 00 00 00 70 00 00 00 00 1f 1d 01 00 00 00 .....p..........
0x70000ba37700: 00 a7 22 05 01 00 00 00 a0 7a a3 0b 00 70 00 00 .?".....?z?..p..
这里在 monitorenter 的地方打了一个断点, 并且输出了 当前 lockObj 的相关信息之后, 直接 continue, 断点停在了 第二个 monitorenter
我们可以整理一些结论
1. 在第一个断点的时候, lockObj 没有锁, 就一个 0x101, 第二个断点的时候 已经加上了偏向锁 偏向于 main 线程
2. 第二个断点相比于 第一个断点, [0x70000ba37618 - 0x70000ba37628) 增加了一个 BasicLockObject 关联 lockObj 对象
那么 我们接下来看一下 重入的情况 会走怎么样的流程呢
分配了 BasicObjectLock 之后情况如下
(lldb) b 0x10524f9dc
Breakpoint 4: address = 0x000000010524f9dc
(lldb) c
Process 2762 resuming
Process 2762 stopped
* thread #5, stop reason = breakpoint 4.1frame #0: 0x000000010524f9dc
-> 0x10524f9dc: incq %r130x10524f9df: movq %rax, 0x8(%rsi)0x10524f9e3: movq 0x8(%rsi), %rcx0x10524f9e7: movq (%rcx), %rax
Target 0: (java) stopped.
(lldb) re r
General Purpose Registers:rax = 0x0000000747bb8798rbx = 0x00000000000000c2rcx = 0x000070000ba37608rdx = 0x000070000ba37628rdi = 0x0000000101806000rsi = 0x000070000ba37608rbp = 0x000070000ba37670rsp = 0x000070000ba37608r8 = 0x0000000000000000r9 = 0x0000000000000020r10 = 0x0000000104b0b270 libjvm.dylib`TemplateInterpreter::_active_table + 18432r11 = 0x00006fff0a229200r12 = 0x0000000000000000r13 = 0x000000011d1eff97r14 = 0x000070000ba376a8r15 = 0x0000000101806000rip = 0x000000010524f9dcrflags = 0x0000000000000246cs = 0x000000000000002bfs = 0x0000000000000000gs = 0x0000000000000000
(lldb) x 0x000070000ba37608 -c 0x100
0x70000ba37608: 98 87 bb 47 07 00 00 00 98 87 bb 47 07 00 00 00 ..?G......?G....
0x70000ba37618: 98 87 bb 47 07 00 00 00 98 87 bb 47 07 00 00 00 ..?G......?G....
0x70000ba37628: 08 76 a3 0b 00 70 00 00 94 ff 1e 1d 01 00 00 00 .v?..p...?......
0x70000ba37638: a8 76 a3 0b 00 70 00 00 88 00 1f 1d 01 00 00 00 ?v?..p..........
0x70000ba37648: 00 00 00 00 00 00 00 00 70 82 bb 47 07 00 00 00 ........p.?G....
0x70000ba37658: 00 00 1f 1d 01 00 00 00 00 00 00 00 00 00 00 00 ................
0x70000ba37668: a8 76 a3 0b 00 70 00 00 10 77 a3 0b 00 70 00 00 ?v?..p...w?..p..
0x70000ba37678: f1 09 20 05 01 00 00 00 00 00 00 00 00 00 00 00 ?. .............
0x70000ba37688: 00 00 00 00 00 00 00 00 98 87 bb 47 07 00 00 00 ..........?G....
0x70000ba37698: 98 87 bb 47 07 00 00 00 98 87 bb 47 07 00 00 00 ..?G......?G....
0x70000ba376a8: 88 87 bb 47 07 00 00 00 a0 1f 00 00 03 00 00 00 ..?G....?.......
0x70000ba376b8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x70000ba376c8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x70000ba376d8: 00 80 a3 0b 00 70 00 00 20 78 a3 0b 00 70 00 00 ..?..p.. x?..p..
0x70000ba376e8: 50 7d a3 0b 00 70 00 00 0a 00 00 00 00 70 00 00 P}?..p.......p..
0x70000ba376f8: 00 00 1f 1d 01 00 00 00 00 a7 22 05 01 00 00 00 .........?".....
0x70000ba37628 : 标记点的是 expression bottom, 第二次 monitorenter 的时候是 0x000070000ba37618
现在有多了一个 BasicLockObject 了, 变成了 0x000070000ba37608
加锁的流程如下
(lldb) stepi -c 7
Process 2762 stopped
* thread #5, stop reason = instruction step intoframe #0: 0x000000010524f9f5
-> 0x10524f9f5: jne 0x10524fa7c0x10524f9fb: movl 0x8(%rcx), %ebx0x10524f9fe: shlq $0x3, %rbx0x10524fa02: movq 0xb0(%rbx), %rbx
Target 0: (java) stopped.
(lldb) stepi
Process 2762 stopped
* thread #5, stop reason = instruction step intoframe #0: 0x000000010524f9fb
-> 0x10524f9fb: movl 0x8(%rcx), %ebx0x10524f9fe: shlq $0x3, %rbx0x10524fa02: movq 0xb0(%rbx), %rbx0x10524fa09: orq %r15, %rbx
Target 0: (java) stopped.
(lldb) re r
General Purpose Registers:rax = 0x0000000101806005rbx = 0x0000000000000005rcx = 0x0000000747bb8798rdx = 0x000070000ba37628rdi = 0x0000000101806000rsi = 0x000070000ba37608rbp = 0x000070000ba37670rsp = 0x000070000ba37608r8 = 0x0000000000000000r9 = 0x0000000000000020r10 = 0x0000000104b0b270 libjvm.dylib`TemplateInterpreter::_active_table + 18432r11 = 0x00006fff0a229200r12 = 0x0000000000000000r13 = 0x000000011d1eff98r14 = 0x000070000ba376a8r15 = 0x0000000101806000rip = 0x000000010524f9fbrflags = 0x0000000000000246cs = 0x000000000000002bfs = 0x0000000000000000gs = 0x0000000000000000(lldb) stepi
Process 2762 stopped
* thread #5, stop reason = instruction step intoframe #0: 0x000000010524f9fe
-> 0x10524f9fe: shlq $0x3, %rbx0x10524fa02: movq 0xb0(%rbx), %rbx0x10524fa09: orq %r15, %rbx0x10524fa0c: xorq %rax, %rbx
Target 0: (java) stopped.
(lldb) stepi
Process 2762 stopped
* thread #5, stop reason = instruction step intoframe #0: 0x000000010524fa02
-> 0x10524fa02: movq 0xb0(%rbx), %rbx0x10524fa09: orq %r15, %rbx0x10524fa0c: xorq %rax, %rbx0x10524fa0f: andq $-0x79, %rbx
Target 0: (java) stopped.
(lldb) stepi
Process 2762 stopped
* thread #5, stop reason = instruction step intoframe #0: 0x000000010524fa09
-> 0x10524fa09: orq %r15, %rbx0x10524fa0c: xorq %rax, %rbx0x10524fa0f: andq $-0x79, %rbx0x10524fa13: je 0x10524fd05
Target 0: (java) stopped.
(lldb) stepi
Process 2762 stopped
* thread #5, stop reason = instruction step intoframe #0: 0x000000010524fa0c
-> 0x10524fa0c: xorq %rax, %rbx0x10524fa0f: andq $-0x79, %rbx0x10524fa13: je 0x10524fd050x10524fa19: testq $0x7, %rbx
Target 0: (java) stopped.
(lldb) stepi
Process 2762 stopped
* thread #5, stop reason = instruction step intoframe #0: 0x000000010524fa0f
-> 0x10524fa0f: andq $-0x79, %rbx0x10524fa13: je 0x10524fd050x10524fa19: testq $0x7, %rbx0x10524fa20: jne 0x10524fa69
Target 0: (java) stopped.
(lldb) re r
General Purpose Registers:rax = 0x0000000101806005rbx = 0x0000000000000000rcx = 0x0000000747bb8798rdx = 0x000070000ba37628rdi = 0x0000000101806000rsi = 0x000070000ba37608rbp = 0x000070000ba37670rsp = 0x000070000ba37608r8 = 0x0000000000000000r9 = 0x0000000000000020r10 = 0x0000000104b0b270 libjvm.dylib`TemplateInterpreter::_active_table + 18432r11 = 0x00006fff0a229200r12 = 0x0000000000000000r13 = 0x000000011d1eff98r14 = 0x000070000ba376a8r15 = 0x0000000101806000rip = 0x000000010524fa0frflags = 0x0000000000000246cs = 0x000000000000002bfs = 0x0000000000000000gs = 0x0000000000000000(lldb) stepi
Process 2762 stopped
* thread #5, stop reason = instruction step intoframe #0: 0x000000010524fa13
-> 0x10524fa13: je 0x10524fd050x10524fa19: testq $0x7, %rbx0x10524fa20: jne 0x10524fa690x10524fa22: testq $0x300, %rbx ; imm = 0x300
Target 0: (java) stopped.
(lldb) stepi
Process 2762 stopped
* thread #5, stop reason = instruction step intoframe #0: 0x000000010524fd05
-> 0x10524fd05: movq %r13, -0x40(%rbp)0x10524fd09: movl %eax, -0x16000(%rsp)0x10524fd10: movzbl (%r13), %ebx0x10524fd15: movabsq $0x104b0b270, %r10 ; imm = 0x104B0B270
Target 0: (java) stopped.
发现当前线程 和 偏向锁上面记录的线程, epoch 一样, 直接 加锁完成
偏向锁的退出
(lldb) p _active_table._table[9][195]
(address) $1 = 0x000000010524fde0 "XH;"
(lldb) b 0x000000010524fde1
Breakpoint 5: address = 0x000000010524fde1
(lldb) c
Process 2762 resuming
Process 2762 stopped
* thread #5, stop reason = breakpoint 5.1frame #0: 0x000000010524fde1
-> 0x10524fde1: cmpq (%rax), %rax0x10524fde4: movq -0x48(%rbp), %rsi0x10524fde8: leaq -0x48(%rbp), %rdx0x10524fdec: jmp 0x10524fdfc
Target 0: (java) stopped.
(lldb) re r
General Purpose Registers:rax = 0x0000000747bb8798rbx = 0x00000000000000c3rcx = 0x0000000747bb8798rdx = 0x000070000ba37628rdi = 0x0000000101806000rsi = 0x000070000ba37608rbp = 0x000070000ba37670rsp = 0x000070000ba37608r8 = 0x0000000000000000r9 = 0x0000000000000020r10 = 0x0000000104b0aa70 libjvm.dylib`TemplateInterpreter::_active_table + 16384r11 = 0x00006fff0a229200r12 = 0x0000000000000000r13 = 0x000000011d1eff99r14 = 0x000070000ba376a8r15 = 0x0000000101806000rip = 0x000000010524fde1rflags = 0x0000000000000206cs = 0x000000000000002bfs = 0x0000000000000000gs = 0x0000000000000000(lldb) p ((oopDesc*)0x0000000747bb8798)->print()
com.hx.test04.Test26SynchronizeReentrantObject
{0x0000000747bb8798} - klass: 'com/hx/test04/Test26SynchronizeReentrantObject'- ---- fields (total size 5 words):- 'f01' 'I' @12 0- 'f02' 'I' @16 0- 'f03' 'I' @20 0- 'f04' 'I' @24 0- 'f05' 'I' @28 0- private 'identStr' 'Ljava/lang/String;' @32 "xyz"{0x0000000747bb87c0} (e8f770f8 0)
(lldb) x 0x000070000ba37608 -c 0x100
0x70000ba37608: 98 87 bb 47 07 00 00 00 98 87 bb 47 07 00 00 00 ..?G......?G....
0x70000ba37618: 98 87 bb 47 07 00 00 00 98 87 bb 47 07 00 00 00 ..?G......?G....
0x70000ba37628: 08 76 a3 0b 00 70 00 00 98 ff 1e 1d 01 00 00 00 .v?..p...?......
0x70000ba37638: a8 76 a3 0b 00 70 00 00 88 00 1f 1d 01 00 00 00 ?v?..p..........
0x70000ba37648: 00 00 00 00 00 00 00 00 70 82 bb 47 07 00 00 00 ........p.?G....
0x70000ba37658: 00 00 1f 1d 01 00 00 00 00 00 00 00 00 00 00 00 ................
0x70000ba37668: a8 76 a3 0b 00 70 00 00 10 77 a3 0b 00 70 00 00 ?v?..p...w?..p..
0x70000ba37678: f1 09 20 05 01 00 00 00 00 00 00 00 00 00 00 00 ?. .............
0x70000ba37688: 00 00 00 00 00 00 00 00 98 87 bb 47 07 00 00 00 ..........?G....
0x70000ba37698: 98 87 bb 47 07 00 00 00 98 87 bb 47 07 00 00 00 ..?G......?G....
0x70000ba376a8: 88 87 bb 47 07 00 00 00 a0 1f 00 00 03 00 00 00 ..?G....?.......
0x70000ba376b8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x70000ba376c8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x70000ba376d8: 00 80 a3 0b 00 70 00 00 20 78 a3 0b 00 70 00 00 ..?..p.. x?..p..
0x70000ba376e8: 50 7d a3 0b 00 70 00 00 0a 00 00 00 00 70 00 00 P}?..p.......p..
0x70000ba376f8: 00 00 1f 1d 01 00 00 00 00 a7 22 05 01 00 00 00 .........?".....// continue, 之后 断点停留在了 第二个 monitorexit
(lldb) c
Process 2762 resuming
Process 2762 stopped
* thread #5, stop reason = breakpoint 5.1frame #0: 0x000000010524fde1
-> 0x10524fde1: cmpq (%rax), %rax0x10524fde4: movq -0x48(%rbp), %rsi0x10524fde8: leaq -0x48(%rbp), %rdx0x10524fdec: jmp 0x10524fdfc
Target 0: (java) stopped.
(lldb) x 0x000070000ba37608 -c 0x100
0x70000ba37608: 98 87 bb 47 07 00 00 00 00 00 00 00 00 00 00 00 ..?G............
0x70000ba37618: 98 87 bb 47 07 00 00 00 98 87 bb 47 07 00 00 00 ..?G......?G....
0x70000ba37628: 08 76 a3 0b 00 70 00 00 99 ff 1e 1d 01 00 00 00 .v?..p...?......
0x70000ba37638: a8 76 a3 0b 00 70 00 00 88 00 1f 1d 01 00 00 00 ?v?..p..........
0x70000ba37648: 00 00 00 00 00 00 00 00 70 82 bb 47 07 00 00 00 ........p.?G....
0x70000ba37658: 00 00 1f 1d 01 00 00 00 00 00 00 00 00 00 00 00 ................
0x70000ba37668: a8 76 a3 0b 00 70 00 00 10 77 a3 0b 00 70 00 00 ?v?..p...w?..p..
0x70000ba37678: f1 09 20 05 01 00 00 00 00 00 00 00 00 00 00 00 ?. .............
0x70000ba37688: 00 00 00 00 00 00 00 00 98 87 bb 47 07 00 00 00 ..........?G....
0x70000ba37698: 98 87 bb 47 07 00 00 00 98 87 bb 47 07 00 00 00 ..?G......?G....
0x70000ba376a8: 88 87 bb 47 07 00 00 00 a0 1f 00 00 03 00 00 00 ..?G....?.......
0x70000ba376b8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x70000ba376c8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x70000ba376d8: 00 80 a3 0b 00 70 00 00 20 78 a3 0b 00 70 00 00 ..?..p.. x?..p..
0x70000ba376e8: 50 7d a3 0b 00 70 00 00 0a 00 00 00 00 70 00 00 P}?..p.......p..
0x70000ba376f8: 00 00 1f 1d 01 00 00 00 00 a7 22 05 01 00 00 00 .........?".....
(lldb) b 0x1052500ec
Breakpoint 6: address = 0x00000001052500ec
(lldb) c
Process 2762 resuming
Process 2762 stopped
* thread #5, stop reason = breakpoint 6.1frame #0: 0x00000001052500ec
-> 0x1052500ec: movq (%rcx), %rdx0x1052500ef: andq $0x7, %rdx0x1052500f3: cmpq $0x5, %rdx0x1052500f7: je 0x105250378
Target 0: (java) stopped.
(lldb) stepi -c 3
Process 2762 stopped
* thread #5, stop reason = instruction step intoframe #0: 0x00000001052500f7
-> 0x1052500f7: je 0x1052503780x1052500fd: movq (%rax), %rdx0x105250100: testq %rdx, %rdx0x105250103: je 0x105250378
Target 0: (java) stopped.
(lldb) stepi
Process 2762 stopped
* thread #5, stop reason = instruction step intoframe #0: 0x0000000105250378
-> 0x105250378: movq -0x40(%rbp), %r130x10525037c: popq %rax0x10525037d: movzbl 0x1(%r13), %ebx0x105250382: incq %r13
Target 0: (java) stopped.
(lldb) x 0x000070000ba37608 -c 0x100
0x70000ba37608: 98 87 bb 47 07 00 00 00 00 00 00 00 00 00 00 00 ..?G............
0x70000ba37618: 98 87 bb 47 07 00 00 00 00 00 00 00 00 00 00 00 ..?G............
0x70000ba37628: 08 76 a3 0b 00 70 00 00 a5 ff 1e 1d 01 00 00 00 .v?..p..??......
0x70000ba37638: a8 76 a3 0b 00 70 00 00 88 00 1f 1d 01 00 00 00 ?v?..p..........
0x70000ba37648: 00 00 00 00 00 00 00 00 70 82 bb 47 07 00 00 00 ........p.?G....
0x70000ba37658: 00 00 1f 1d 01 00 00 00 00 00 00 00 00 00 00 00 ................
0x70000ba37668: a8 76 a3 0b 00 70 00 00 10 77 a3 0b 00 70 00 00 ?v?..p...w?..p..
0x70000ba37678: f1 09 20 05 01 00 00 00 00 00 00 00 00 00 00 00 ?. .............
0x70000ba37688: 00 00 00 00 00 00 00 00 98 87 bb 47 07 00 00 00 ..........?G....
0x70000ba37698: 98 87 bb 47 07 00 00 00 98 87 bb 47 07 00 00 00 ..?G......?G....
0x70000ba376a8: 88 87 bb 47 07 00 00 00 a0 1f 00 00 03 00 00 00 ..?G....?.......
0x70000ba376b8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x70000ba376c8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x70000ba376d8: 00 80 a3 0b 00 70 00 00 20 78 a3 0b 00 70 00 00 ..?..p.. x?..p..
0x70000ba376e8: 50 7d a3 0b 00 70 00 00 0a 00 00 00 00 70 00 00 P}?..p.......p..
0x70000ba376f8: 00 00 1f 1d 01 00 00 00 00 a7 22 05 01 00 00 00 .........?".....
可以看到这里的两次偏向锁的退出 主要的事情是 吧对应的 BasicLockObject.obj 置空处理(一则是标记obj已经不持有锁了, 二则是其他的对象可以复用)
偏向线程同步块执行完成 非偏向线程尝试加锁
package com.hx.test04;/*** Test27MultiThreadInBiasLock** @author Jerry.X.He <970655147@qq.com>* @version 1.0* @date 2020-04-03 15:14*/
public class Test27MultiThreadInBiasLock implements Cloneable {// identStrprivate String identStr = "xyz";int f01;int f02;int f03;int f04;int f05;// Test25SynchronizeObjectpublic static void main(String[] args) throws Exception {Test27MultiThreadInBiasLock lockObj = new Test27MultiThreadInBiasLock();doClone(lockObj);synchronized (lockObj) {}new Thread() {@Overridepublic void run() {doClone(lockObj);synchronized (lockObj) {}}}.start();Test25SynchronizeObject.sleep(2000);}// doCloneprivate static void doClone(Test27MultiThreadInBiasLock obj) {try {obj.clone();} catch (Exception e) {e.printStackTrace();}}}
lldb 调试如下
(lldb) p _active_table._table[9][194]
(address) $0 = 0x000000010584f980 "XH;"
(lldb) c
Process 2916 resuming
Process 2916 stopped
* thread #5, stop reason = breakpoint 3.1frame #0: 0x0000000103171ab4 libjvm.dylib`::JVM_Clone(env=0x0000000101008a28, handle=0x000070000f2635c8) at jvm.cpp:627:28624 JVM_ENTRY(jobject, JVM_Clone(JNIEnv* env, jobject handle))625 JVMWrapper("JVM_Clone");626 Handle obj(THREAD, JNIHandles::resolve_non_null(handle));
-> 627 const KlassHandle klass (THREAD, obj->klass());628 JvmtiVMObjectAllocEventCollector oam;629 630 #ifdef ASSERT
Target 0: (java) stopped.(lldb) c
Process 2916 resuming
Process 2916 stopped
* thread #38, name = 'Java: Thread-0', stop reason = breakpoint 3.1frame #0: 0x0000000103171ab4 libjvm.dylib`::JVM_Clone(env=0x0000000101054228, handle=0x00007000113c65e0) at jvm.cpp:627:28624 JVM_ENTRY(jobject, JVM_Clone(JNIEnv* env, jobject handle))625 JVMWrapper("JVM_Clone");626 Handle obj(THREAD, JNIHandles::resolve_non_null(handle));
-> 627 const KlassHandle klass (THREAD, obj->klass());628 JvmtiVMObjectAllocEventCollector oam;629 630 #ifdef ASSERT
Target 0: (java) stopped.(lldb) b 0x000000010584f980
Breakpoint 4: address = 0x000000010584f980
(lldb) c
Process 2916 resuming
Process 2916 stopped
* thread #38, name = 'Java: Thread-0', stop reason = breakpoint 4.1frame #0: 0x000000010584f980
-> 0x10584f980: popq %rax0x10584f981: cmpq (%rax), %rax0x10584f984: xorl %esi, %esi0x10584f986: movq -0x48(%rbp), %rcx
Target 0: (java) stopped.
(lldb) re r
General Purpose Registers:rax = 0x0000000747bb8ec0rbx = 0x00000000000000c2rcx = 0x00000000000000cbrdx = 0x0000000000000000rdi = 0x000000010580b220rsi = 0x00007000113c6650rbp = 0x00007000113c66f8rsp = 0x00007000113c66a8r8 = 0x0000000000000000r9 = 0x0000000100315a90r10 = 0x0000000103b0b270 libjvm.dylib`TemplateInterpreter::_active_table + 18432r11 = 0x00007000113c65e0r12 = 0x0000000000000000r13 = 0x000000011d46f845r14 = 0x00007000113c6718r15 = 0x0000000101054000rip = 0x000000010584f980rflags = 0x0000000000000202cs = 0x000000000000002bfs = 0x0000000000000000gs = 0x0000000000000000(lldb) p ((oopDesc*)0x0000000747bb8ec0)->print()
com.hx.test04.Test27MultiThreadInBiasLock
{0x0000000747bb8ec0} - klass: 'com/hx/test04/Test27MultiThreadInBiasLock'- ---- fields (total size 5 words):- 'f01' 'I' @12 0- 'f02' 'I' @16 0- 'f03' 'I' @20 0- 'f04' 'I' @24 0- 'f05' 'I' @28 0- private 'identStr' 'Ljava/lang/String;' @32 "xyz"{0x0000000747bb8ee8} (e8f771dd 0)
(lldb) p ((oopDesc*)0x0000000747bb8ec0)->mark()->biased_locker()->threadObj()->print()
java.lang.Thread
{0x0000000747f069d8} - klass: 'java/lang/Thread'- ---- fields (total size 47 words):- private 'priority' 'I' @12 5- private 'eetop' 'J' @16 4311779328 (1008800 1)- private 'stackSize' 'J' @24 0 (0 0)- private 'nativeParkEventPointer' 'J' @32 0 (0 0)- private 'tid' 'J' @40 1 (1 0)- private volatile 'threadStatus' 'I' @48 5- private 'single_step' 'Z' @52 false- private 'daemon' 'Z' @53 false- private 'stillborn' 'Z' @54 false- private volatile 'name' 'Ljava/lang/String;' @56 "main"{0x0000000747f06b50} (e8fe0d6a 0)- private 'threadQ' 'Ljava/lang/Thread;' @60 NULL (0 0)- private 'target' 'Ljava/lang/Runnable;' @64 NULL (0 e8fe0c85)- private 'group' 'Ljava/lang/ThreadGroup;' @68 a 'java/lang/ThreadGroup'{0x0000000747f06428} (e8fe0c85 e8fc0af7)- private 'contextClassLoader' 'Ljava/lang/ClassLoader;' @72 a 'jdk/internal/loader/ClassLoaders$AppClassLoader'{0x0000000747e057b8} (e8fc0af7 e8fe0d91)- private 'inheritedAccessControlContext' 'Ljava/security/AccessControlContext;' @76 a 'java/security/AccessControlContext'{0x0000000747f06c88} (e8fe0d91 e8fe2fb8)- 'threadLocals' 'Ljava/lang/ThreadLocal$ThreadLocalMap;' @80 a 'java/lang/ThreadLocal$ThreadLocalMap'{0x0000000747f17dc0} (e8fe2fb8 0)- 'inheritableThreadLocals' 'Ljava/lang/ThreadLocal$ThreadLocalMap;' @84 NULL (0 0)- volatile 'parkBlocker' 'Ljava/lang/Object;' @88 NULL (0 0)- private volatile 'blocker' 'Lsun/nio/ch/Interruptible;' @92 NULL (0 e8fe0d70)- private final 'blockerLock' 'Ljava/lang/Object;' @96 a 'java/lang/Object'{0x0000000747f06b80} (e8fe0d70 0)- private volatile 'uncaughtExceptionHandler' 'Ljava/lang/Thread$UncaughtExceptionHandler;' @100 NULL (0 0)- 'threadLocalRandomSeed' 'J' @232 0 (0 0)- 'threadLocalRandomProbe' 'I' @240 0- 'threadLocalRandomSecondarySeed' 'I' @244 0
(lldb) b 0x10584f9e3
Breakpoint 5: address = 0x000000010584f9e3
(lldb) c
Process 2916 resuming
Process 2916 stopped
* thread #38, name = 'Java: Thread-0', stop reason = breakpoint 5.1frame #0: 0x000000010584f9e3
-> 0x10584f9e3: movq 0x8(%rsi), %rcx0x10584f9e7: movq (%rcx), %rax0x10584f9ea: movq %rax, %rbx0x10584f9ed: andq $0x7, %rbx
Target 0: (java) stopped.
(lldb) stepi -c 4
Process 2916 stopped
* thread #38, name = 'Java: Thread-0', stop reason = instruction step intoframe #0: 0x000000010584f9f1
-> 0x10584f9f1: cmpq $0x5, %rbx0x10584f9f5: jne 0x10584fa7c0x10584f9fb: movl 0x8(%rcx), %ebx0x10584f9fe: shlq $0x3, %rbx
Target 0: (java) stopped.
(lldb) stepi
Process 2916 stopped
* thread #38, name = 'Java: Thread-0', stop reason = instruction step intoframe #0: 0x000000010584f9f5
-> 0x10584f9f5: jne 0x10584fa7c0x10584f9fb: movl 0x8(%rcx), %ebx0x10584f9fe: shlq $0x3, %rbx0x10584fa02: movq 0xb0(%rbx), %rbx
Target 0: (java) stopped.
(lldb) stepi
Process 2916 stopped
* thread #38, name = 'Java: Thread-0', stop reason = instruction step intoframe #0: 0x000000010584f9fb
-> 0x10584f9fb: movl 0x8(%rcx), %ebx0x10584f9fe: shlq $0x3, %rbx0x10584fa02: movq 0xb0(%rbx), %rbx0x10584fa09: orq %r15, %rbx
Target 0: (java) stopped.
(lldb) stepi -c 4
Process 2916 stopped
* thread #38, name = 'Java: Thread-0', stop reason = instruction step intoframe #0: 0x000000010584fa0c
-> 0x10584fa0c: xorq %rax, %rbx0x10584fa0f: andq $-0x79, %rbx0x10584fa13: je 0x10584fd050x10584fa19: testq $0x7, %rbx
Target 0: (java) stopped.
(lldb) stepi
Process 2916 stopped
* thread #38, name = 'Java: Thread-0', stop reason = instruction step intoframe #0: 0x000000010584fa0f
-> 0x10584fa0f: andq $-0x79, %rbx0x10584fa13: je 0x10584fd050x10584fa19: testq $0x7, %rbx0x10584fa20: jne 0x10584fa69
Target 0: (java) stopped.
(lldb) stepi
Process 2916 stopped
* thread #38, name = 'Java: Thread-0', stop reason = instruction step intoframe #0: 0x000000010584fa13
-> 0x10584fa13: je 0x10584fd050x10584fa19: testq $0x7, %rbx0x10584fa20: jne 0x10584fa690x10584fa22: testq $0x300, %rbx ; imm = 0x300
Target 0: (java) stopped.
(lldb) stepi
Process 2916 stopped
* thread #38, name = 'Java: Thread-0', stop reason = instruction step intoframe #0: 0x000000010584fa19
-> 0x10584fa19: testq $0x7, %rbx0x10584fa20: jne 0x10584fa690x10584fa22: testq $0x300, %rbx ; imm = 0x300 0x10584fa29: jne 0x10584fa48
Target 0: (java) stopped.
(lldb) stepi
Process 2916 stopped
* thread #38, name = 'Java: Thread-0', stop reason = instruction step intoframe #0: 0x000000010584fa20
-> 0x10584fa20: jne 0x10584fa690x10584fa22: testq $0x300, %rbx ; imm = 0x300 0x10584fa29: jne 0x10584fa480x10584fa2b: andq $0x37f, %rax ; imm = 0x37F
Target 0: (java) stopped.
(lldb) stepi
Process 2916 stopped
* thread #38, name = 'Java: Thread-0', stop reason = instruction step intoframe #0: 0x000000010584fa22
-> 0x10584fa22: testq $0x300, %rbx ; imm = 0x300 0x10584fa29: jne 0x10584fa480x10584fa2b: andq $0x37f, %rax ; imm = 0x37F 0x10584fa32: movq %rax, %rbx
Target 0: (java) stopped.
(lldb) stepi
Process 2916 stopped
* thread #38, name = 'Java: Thread-0', stop reason = instruction step intoframe #0: 0x000000010584fa29
-> 0x10584fa29: jne 0x10584fa480x10584fa2b: andq $0x37f, %rax ; imm = 0x37F 0x10584fa32: movq %rax, %rbx0x10584fa35: orq %r15, %rbx
Target 0: (java) stopped.
(lldb) stepi
Process 2916 stopped
* thread #38, name = 'Java: Thread-0', stop reason = instruction step intoframe #0: 0x000000010584fa2b
-> 0x10584fa2b: andq $0x37f, %rax ; imm = 0x37F 0x10584fa32: movq %rax, %rbx0x10584fa35: orq %r15, %rbx0x10584fa38: lock
Target 0: (java) stopped.
(lldb) stepi
Process 2916 stopped
* thread #38, name = 'Java: Thread-0', stop reason = instruction step intoframe #0: 0x000000010584fa32
-> 0x10584fa32: movq %rax, %rbx0x10584fa35: orq %r15, %rbx0x10584fa38: lock 0x10584fa39: cmpxchgq %rbx, (%rcx)
Target 0: (java) stopped.
(lldb) stepi
Process 2916 stopped
* thread #38, name = 'Java: Thread-0', stop reason = instruction step intoframe #0: 0x000000010584fa35
-> 0x10584fa35: orq %r15, %rbx0x10584fa38: lock 0x10584fa39: cmpxchgq %rbx, (%rcx)0x10584fa3d: jne 0x10584faa5
Target 0: (java) stopped.
(lldb) stepi
Process 2916 stopped
* thread #38, name = 'Java: Thread-0', stop reason = instruction step intoframe #0: 0x000000010584fa38
-> 0x10584fa38: lock 0x10584fa39: cmpxchgq %rbx, (%rcx)0x10584fa3d: jne 0x10584faa50x10584fa43: jmp 0x10584fd05
Target 0: (java) stopped.
(lldb) stepi
Process 2916 stopped
* thread #38, name = 'Java: Thread-0', stop reason = instruction step intoframe #0: 0x000000010584fa3d
-> 0x10584fa3d: jne 0x10584faa50x10584fa43: jmp 0x10584fd050x10584fa48: movl 0x8(%rcx), %ebx0x10584fa4b: shlq $0x3, %rbx
Target 0: (java) stopped.
(lldb) re r
General Purpose Registers:rax = 0x0000000101008805rbx = 0x0000000101054005rcx = 0x0000000747bb8ec0rdx = 0x00007000113c66b0rdi = 0x000000010580b220rsi = 0x00007000113c66a0rbp = 0x00007000113c66f8rsp = 0x00007000113c66a0r8 = 0x0000000000000000r9 = 0x0000000100315a90r10 = 0x0000000103b0b270 libjvm.dylib`TemplateInterpreter::_active_table + 18432r11 = 0x00007000113c65e0r12 = 0x0000000000000000r13 = 0x000000011d46f846r14 = 0x00007000113c6718r15 = 0x0000000101054000rip = 0x000000010584fa3drflags = 0x0000000000000287cs = 0x000000000000002bfs = 0x0000000000000000gs = 0x0000000000000000(lldb) stepi
Process 2916 stopped
* thread #38, name = 'Java: Thread-0', stop reason = instruction step intoframe #0: 0x000000010584faa5
-> 0x10584faa5: callq 0x10584faaf0x10584faaa: jmp 0x10584fd050x10584faaf: leaq 0x8(%rsp), %rax0x10584fab4: movq %r13, -0x40(%rbp)
Target 0: (java) stopped.
到 monitorenter 的代码的时候, lockObj 的偏向锁已经偏向于 main 线程, 并且 main 线程已经退出了 同步代码块
然后 Thread-0 走同步的流程, 申请 BasicLockObject, 然后创建 走的是 正常更新偏向锁的流程, 但是 由于 lockObj 的偏向锁已经偏向于 main 线程, 因此 cas 更新 mark 的时候失败了, 之后 走的 InterpreterRuntime::monitorenter 的流程
然后 这部分的处理, 在这里 就不展开了
偏向锁可以 偏向线程1 之后 偏向线程2 么?
撤销偏向锁的调用的地方
上面第二行传入 变量的方法, 调用的地方
上面第二行传入 变量的方法, 调用的地方, 可能是 true, 这个方法是 BiasedLocking::revoke_and_rebias
只有在 synchronizer.cpp 里面的 fast_enter 方法里面可能传入 true
但是 就算是这里传入的是 true, 后面创建了 批量Rebias 的 VMOperation, operation 里面返回的状态也是 BiasedLocking::BIAS_REVOKED, 后面还是走 锁升级 的处理
所以 应该是不会出现这种情况, 存在竞争 锁会 inflate
完
参考
09 给对象添加偏向锁的调试
10 偏向锁的退出的调试