呵呵 接上一篇 17 PrintAssembly的汇编结果分析的HelloWorld
我们这里分析一下 常见的 基于双检锁的单例的 PrintAssembly 的 汇编结果的分析
虽然 java 代码这边写起来简单, 就这么 几句代码, 但是 想要完整的表达 这几句代码的语义 对应的汇编代码 就是很长的篇幅, 而且 还有很多的其他的函数代码 是直接 以 call 的形式调用的
此用例 也是参照于文章 : JVM执行篇:使用HSDIS插件分析JVM代码执行细节--转
呵呵 本文的用例, 相比于 17 PrintAssembly的汇编结果分析的HelloWorld 要复杂一些
以下代码, 输出 基于 jdk 8
package com.hx.test05;
/**
* SinglePrintAssembly
*
* @author Jerry.X.He <[email protected]>
* @version 1.0
* @date 2020-04-10 15:52
*/
public class Test03SingletonPrintAssembly {
// INSTANCE
private static volatile Test03SingletonPrintAssembly INSTANCE;
// Test03SingletonPrintAssembly
// -Xcomp -XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly -XX:CompileCommand=dontinline,*Test03SingletonPrintAssembly.getInstance -XX:CompileCommand=compileonly,*Test03SingletonPrintAssembly.getInstance
public static void main(String[] args) {
Test03SingletonPrintAssembly.getInstance();
}
// getInstance
public static Test03SingletonPrintAssembly getInstance() {
if(INSTANCE == null) {
synchronized (Test03SingletonPrintAssembly.class) {
if(INSTANCE == null) {
INSTANCE = new Test03SingletonPrintAssembly();
}
}
}
return INSTANCE;
}
}
对应的字节码信息如下, 可以用于 之后汇编代码的参照
master:classes jerry$ javap -c com/hx/test05/Test03SingletonPrintAssembly.class
Compiled from "Test03SingletonPrintAssembly.java"
public class com.hx.test05.Test03SingletonPrintAssembly {
public com.hx.test05.Test03SingletonPrintAssembly();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."":()V
4: return
public static void main(java.lang.String[]);
Code:
0: invokestatic #2 // Method getInstance:()Lcom/hx/test05/Test03SingletonPrintAssembly;
3: pop
4: return
public static com.hx.test05.Test03SingletonPrintAssembly getInstance();
Code:
0: getstatic #3 // Field INSTANCE:Lcom/hx/test05/Test03SingletonPrintAssembly;
3: ifnonnull 37
6: ldc #4 // class com/hx/test05/Test03SingletonPrintAssembly
8: dup
9: astore_0
10: monitorenter
11: getstatic #3 // Field INSTANCE:Lcom/hx/test05/Test03SingletonPrintAssembly;
14: ifnonnull 27
17: new #4 // class com/hx/test05/Test03SingletonPrintAssembly
20: dup
21: invokespecial #5 // Method "":()V
24: putstatic #3 // Field INSTANCE:Lcom/hx/test05/Test03SingletonPrintAssembly;
27: aload_0
28: monitorexit
29: goto 37
32: astore_1
33: aload_0
34: monitorexit
35: aload_1
36: athrow
37: getstatic #3 // Field INSTANCE:Lcom/hx/test05/Test03SingletonPrintAssembly;
40: areturn
Exception table:
from to target type
11 29 32 any
32 35 32 any
}
可以看出 字节码 的相关代码 还是很好理解的, 不过这里 编译器 增加了一些异常处理的代码 monitorenter - monitorexit 之间, 以及 对于增加的这段异常处理的代码 还增加了一段异常处理
如果你看过之前的一部分文章, 09 给对象添加偏向锁的调试, 那么你会发现 给定的字节码 也有这两个 异常处理, 不过 因为文章的目的并不是讨论这两段异常代码添加的原因, 所以 就不用过多的纠结于此了
CompilerOracle: dontinline *Test03SingletonPrintAssembly.getInstance
CompilerOracle: compileonly *Test03SingletonPrintAssembly.getInstance
Connected to the target VM, address: '127.0.0.1:54885', transport: 'socket'
Loaded disassembler from /Library/Java/JavaVirtualMachines/jdk1.8.0_211.jdk/Contents/Home/jre/lib/hsdis-amd64.dylib
Decoding compiled method 0x000000011f8c1a10:
Code:
[Disassembling for mach='i386:x86-64']
[Entry Point]
[Verified Entry Point]
[Constants]
# {method} {0x00000001172d6fb0} 'getInstance' '()Lcom/hx/test05/Test03SingletonPrintAssembly;' in 'com/hx/test05/Test03SingletonPrintAssembly'
# [sp+0x50] (sp of caller)
// stackOverflow check, 类似的代码可以参见 "15 main方法的栈帧信息"
0x000000011f8c1ba0: mov %eax,-0x14000(%rsp)
// 创建新的栈帧
0x000000011f8c1ba7: push %rbp
0x000000011f8c1ba8: sub $0x40,%rsp
// method_data[0xdc] += 8 // method_data->_trap_hist._array[12]
0x000000011f8c1bac: movabs $0x1172d7108,%rax ; {metadata(method data for {method} {0x00000001172d6fb0} 'getInstance' '()Lcom/hx/test05/Test03SingletonPrintAssembly;' in 'com/hx/test05/Test03SingletonPrintAssembly')}
0x000000011f8c1bb6: mov 0xdc(%rax),%edx
0x000000011f8c1bbc: add $0x8,%edx
0x000000011f8c1bbf: mov %edx,0xdc(%rax)
// rax = method
0x000000011f8c1bc5: movabs $0x1172d6fb0,%rax ; {metadata({method} {0x00000001172d6fb0} 'getInstance' '()Lcom/hx/test05/Test03SingletonPrintAssembly;' in 'com/hx/test05/Test03SingletonPrintAssembly')}
// 执行一段 stack 的更新处理, 然后跳转回来
0x000000011f8c1bcf: and $0x0,%edx
0x000000011f8c1bd2: cmp $0x0,%edx
0x000000011f8c1bd5: je 0x000000011f8c1ea9
// rax = Test03SingletonPrintAssembly.INSTANCE
0x000000011f8c1bdb: movabs $0x795926248,%rax ; {oop(a 'java/lang/Class' = 'com/hx/test05/Test03SingletonPrintAssembly')}
0x000000011f8c1be8: shl $0x3,%rax ;*getstatic INSTANCE
; - com.hx.test05.Test03SingletonPrintAssembly::getInstance@0 (line 25)
0x000000011f8c1be5: mov 0x68(%rax),%eax
// if(Test03SingletonPrintAssembly.INSTANCE != null) goto 0x000000011f8c1e20;
0x000000011f8c1bec: cmp $0x0,%rax
0x000000011f8c1bf0: movabs $0x1172d7108,%rax ; {metadata(method data for {method} {0x00000001172d6fb0} 'getInstance' '()Lcom/hx/test05/Test03SingletonPrintAssembly;' in 'com/hx/test05/Test03SingletonPrintAssembly')}
0x000000011f8c1bfa: movabs $0x108,%rdx
0x000000011f8c1c04: jne 0x000000011f8c1c14
0x000000011f8c1c0a: movabs $0x118,%rdx
// method_data[0x108] += 1 // method_data->_eflags
0x000000011f8c1c14: mov (%rax,%rdx,1),%rsi
0x000000011f8c1c18: lea 0x1(%rsi),%rsi
0x000000011f8c1c1c: mov %rsi,(%rax,%rdx,1)
0x000000011f8c1c20: jne 0x000000011f8c1e20 ;*ifnonnull
; - com.hx.test05.Test03SingletonPrintAssembly::getInstance@3 (line 25)
// ($rsp) + 0x30 = Test03SingletonPrintAssembly.class
// rsi = BasicLockObject
// BasicLockObject.obj = Test03SingletonPrintAssembly.class
0x000000011f8c1c26: movabs $0x795926248,%rdx ; {oop(a 'java/lang/Class' = 'com/hx/test05/Test03SingletonPrintAssembly')}
0x000000011f8c1c30: lea 0x28(%rsp),%rsi
0x000000011f8c1c35: mov %rdx,0x8(%rsi)
// if(!Test03SingletonPrintAssembly.class.has_bias_pattern()) goto 0x000000011f8c1cce;
0x000000011f8c1c39: mov (%rdx),%rax ; implicit exception: dispatches to 0x000000011f8c1ec0
0x000000011f8c1c3c: mov %rax,%rdi
0x000000011f8c1c3f: and $0x7,%rdi
0x000000011f8c1c43: cmp $0x5,%rdi
0x000000011f8c1c47: jne 0x000000011f8c1cce
// mark 掉除了 age 之外的部分, 进行比较, 如果相等 则是偏向锁重入, 直接加锁成功
0x000000011f8c1c4d: mov 0x8(%rdx),%edi
0x000000011f8c1c50: shl $0x3,%rdi
0x000000011f8c1c54: mov 0xa8(%rdi),%rdi
0x000000011f8c1c5b: or %r15,%rdi
0x000000011f8c1c5e: xor %rax,%rdi
0x000000011f8c1c61: and $0xffffffffffffff87,%rdi
0x000000011f8c1c65: je 0x000000011f8c1cf6
// if (lockBits != 0) goto try_revoke_bias
0x000000011f8c1c6b: test $0x7,%rdi
0x000000011f8c1c72: jne 0x000000011f8c1cbb
// if (epoch != 0) goto try_rebias
0x000000011f8c1c74: test $0x300,%rdi
0x000000011f8c1c7b: jne 0x000000011f8c1c9a
// epoch is valid
0x000000011f8c1c7d: and $0x37f,%rax
0x000000011f8c1c84: mov %rax,%rdi
0x000000011f8c1c87: or %r15,%rdi
0x000000011f8c1c8a: lock cmpxchg %rdi,(%rdx)
0x000000011f8c1c8f: jne 0x000000011f8c1ec5
0x000000011f8c1c95: jmpq 0x000000011f8c1cf6
// rebias
0x000000011f8c1c9a: mov 0x8(%rdx),%edi
0x000000011f8c1c9d: shl $0x3,%rdi
0x000000011f8c1ca1: mov 0xa8(%rdi),%rdi
0x000000011f8c1ca8: or %r15,%rdi
0x000000011f8c1cab: lock cmpxchg %rdi,(%rdx)
0x000000011f8c1cb0: jne 0x000000011f8c1ec5
0x000000011f8c1cb6: jmpq 0x000000011f8c1cf6
// revoke
0x000000011f8c1cbb: mov 0x8(%rdx),%edi
0x000000011f8c1cbe: shl $0x3,%rdi
0x000000011f8c1cc2: mov 0xa8(%rdi),%rdi
0x000000011f8c1cc9: lock cmpxchg %rdi,(%rdx)
// 加轻量级锁
0x000000011f8c1cce: mov (%rdx),%rax
0x000000011f8c1cd1: or $0x1,%rax
0x000000011f8c1cd5: mov %rax,(%rsi)
0x000000011f8c1cd8: lock cmpxchg %rsi,(%rdx)
0x000000011f8c1cdd: je 0x000000011f8c1cf6
// 轻量级锁重入
0x000000011f8c1ce3: sub %rsp,%rax
0x000000011f8c1ce6: and $0xfffffffffffff007,%rax
0x000000011f8c1ced: mov %rax,(%rsi)
// 加重量级锁
0x000000011f8c1cf0: jne 0x000000011f8c1ec5 ;*monitorenter
; - com.hx.test05.Test03SingletonPrintAssembly::getInstance@10 (line 26)
// rdx = Test03SingletonPrintAssembly.INSTANCE
0x000000011f8c1cf6: movabs $0x795926248,%rdx ; {oop(a 'java/lang/Class' = 'com/hx/test05/Test03SingletonPrintAssembly')}
0x000000011f8c1d00: mov 0x68(%rdx),%edx
0x000000011f8c1d03: shl $0x3,%rdx ;*getstatic INSTANCE
; - com.hx.test05.Test03SingletonPrintAssembly::getInstance@11 (line 27)
// if(Test03SingletonPrintAssembly.INSTANCE != null) goto 0x000000011f8c1dd5; // monitorexit(已经添加了锁)
0x000000011f8c1d07: cmp $0x0,%rdx
0x000000011f8c1d0b: movabs $0x1172d7108,%rdx ; {metadata(method data for {method} {0x00000001172d6fb0} 'getInstance' '()Lcom/hx/test05/Test03SingletonPrintAssembly;' in 'com/hx/test05/Test03SingletonPrintAssembly')}
0x000000011f8c1d15: movabs $0x128,%rsi
0x000000011f8c1d1f: jne 0x000000011f8c1d2f
0x000000011f8c1d25: movabs $0x138,%rsi
0x000000011f8c1d2f: mov (%rdx,%rsi,1),%rdi
0x000000011f8c1d33: lea 0x1(%rdi),%rdi
0x000000011f8c1d37: mov %rdi,(%rdx,%rsi,1)
0x000000011f8c1d3b: jne 0x000000011f8c1dd5 ;*ifnonnull
; - com.hx.test05.Test03SingletonPrintAssembly::getInstance@14 (line 27)
// rax = 0x60(%r15) = &(thread->_tlab)._top
// 0x70(%r15) = &(thread->_tlab)._end
// if((thread->_tlab)._end < ((thread->_tlab)._top + 0x10)) goto 0x000000011f8c1ed8;
0x000000011f8c1d41: movabs $0x7c0061aa0,%rdx ; {metadata('com/hx/test05/Test03SingletonPrintAssembly')}
0x000000011f8c1d4b: mov 0x60(%r15),%rax
0x000000011f8c1d4f: lea 0x10(%rax),%rdi
0x000000011f8c1d53: cmp 0x70(%r15),%rdi
0x000000011f8c1d57: ja 0x000000011f8c1ed8
// (thread->_tlab)._top = (thread->_tlab)._top + 0x10)
0x000000011f8c1d5d: mov %rdi,0x60(%r15)
// oop.mark = Test03SingletonPrintAssembly.class.prototype_header
0x000000011f8c1d61: mov 0xa8(%rdx),%rcx
0x000000011f8c1d68: mov %rcx,(%rax)
// oop.klass = Test03SingletonPrintAssembly.class
0x000000011f8c1d6b: mov %rdx,%rcx
0x000000011f8c1d6e: shr $0x3,%rcx
0x000000011f8c1d72: mov %ecx,0x8(%rax)
// oop.padding = 0
0x000000011f8c1d75: xor %rcx,%rcx
0x000000011f8c1d78: mov %ecx,0xc(%rax)
// rcx = 0
0x000000011f8c1d7b: xor %rcx,%rcx ;*new ; - com.hx.test05.Test03SingletonPrintAssembly::getInstance@17 (line 28)
// method_data[0x148] &= 0x1; // method_data->_rtm_state
// invoke Test03SingletonPrintAssembly()
0x000000011f8c1d7e: mov %rax,%rsi
0x000000011f8c1d81: movabs $0x1172d7108,%rdi ; {metadata(method data for {method} {0x00000001172d6fb0} 'getInstance' '()Lcom/hx/test05/Test03SingletonPrintAssembly;' in 'com/hx/test05/Test03SingletonPrintAssembly')}
0x000000011f8c1d8b: addq $0x1,0x148(%rdi)
0x000000011f8c1d93: mov %rax,%rsi ;*invokespecial
; - com.hx.test05.Test03SingletonPrintAssembly::getInstance@21 (line 28)
0x000000011f8c1d96: mov %rax,0x20(%rsp)
0x000000011f8c1d9b: nop
0x000000011f8c1d9c: nop
0x000000011f8c1d9d: nop
0x000000011f8c1d9e: nop
0x000000011f8c1d9f: callq 0x000000011f8060a0 ; OopMap{[32]=Oop [48]=Oop off=516}
;*invokespecial
; - com.hx.test05.Test03SingletonPrintAssembly::getInstance@21 (line 28)
; {optimized virtual_call}
// Test03SingletonPrintAssembly.INSTANCE = (0x20(%rsp) >> 3)
0x000000011f8c1da4: movabs $0x795926248,%rax ; {oop(a 'java/lang/Class' = 'com/hx/test05/Test03SingletonPrintAssembly')}
0x000000011f8c1dae: mov 0x20(%rsp),%rdx
0x000000011f8c1db3: mov %rdx,%r10
0x000000011f8c1db6: shr $0x3,%r10
0x000000011f8c1dba: mov %r10d,0x68(%rax)
0x000000011f8c1dbe: shr $0x9,%rax
0x000000011f8c1dc2: movabs $0x10e9f3000,%rdx
0x000000011f8c1dcc: movb $0x0,(%rax,%rdx,1)
0x000000011f8c1dd0: lock addl $0x0,(%rsp) ;*putstatic INSTANCE
; - com.hx.test05.Test03SingletonPrintAssembly::getInstance@24 (line 28)
// monitorexit
// rax = ($rsp) + 0x28
// rsi = ($rsp) + 0x30 = Test03SingletonPrintAssembly.class
0x000000011f8c1dd5: movabs $0x795926248,%rax ; {oop(a 'java/lang/Class' = 'com/hx/test05/Test03SingletonPrintAssembly')}
0x000000011f8c1ddf: lea 0x28(%rsp),%rax
0x000000011f8c1de4: mov 0x8(%rax),%rsi
// if(Test03SingletonPrintAssembly.class.has_bias_pattern()) goto 0x000000011f8c1e10;
0x000000011f8c1de8: mov (%rsi),%rdx
0x000000011f8c1deb: and $0x7,%rdx
0x000000011f8c1def: cmp $0x5,%rdx
0x000000011f8c1df3: je 0x000000011f8c1e10
// 轻量级锁重入
0x000000011f8c1df9: mov (%rax),%rdx
0x000000011f8c1dfc: test %rdx,%rdx
0x000000011f8c1dff: je 0x000000011f8c1e10
// 轻量级锁解锁
0x000000011f8c1e05: lock cmpxchg %rdx,(%rsi)
// 走 InterpreterRuntime::monitorexit
0x000000011f8c1e0a: jne 0x000000011f8c1ee5 ;*monitorexit
; - com.hx.test05.Test03SingletonPrintAssembly::getInstance@28 (line 30)
// method_data[0x158] += 1; // method_data->_data_size
0x000000011f8c1e10: movabs $0x1172d7108,%rax ; {metadata(method data for {method} {0x00000001172d6fb0} 'getInstance' '()Lcom/hx/test05/Test03SingletonPrintAssembly;' in 'com/hx/test05/Test03SingletonPrintAssembly')}
0x000000011f8c1e1a: incl 0x158(%rax) ;*goto
; - com.hx.test05.Test03SingletonPrintAssembly::getInstance@29 (line 30)
// rax = Test03SingletonPrintAssembly.INSTANCE
0x000000011f8c1e20: movabs $0x795926248,%rax ; {oop(a 'java/lang/Class' = 'com/hx/test05/Test03SingletonPrintAssembly')}
0x000000011f8c1e2a: mov 0x68(%rax),%eax
0x000000011f8c1e2d: shl $0x3,%rax ;*getstatic INSTANCE
; - com.hx.test05.Test03SingletonPrintAssembly::getInstance@37 (line 33)
// 销毁栈帧
0x000000011f8c1e31: add $0x40,%rsp
0x000000011f8c1e35: pop %rbp
0x000000011f8c1e36: test %eax,-0xf95ad3c(%rip) # 0x000000010ff67100
; {poll_return}
0x000000011f8c1e3c: retq ;*areturn
; - com.hx.test05.Test03SingletonPrintAssembly::getInstance@40 (line 33)
// ex handle
0x000000011f8c1e3d: mov 0x2a8(%r15),%rax
0x000000011f8c1e44: xor %r10,%r10
0x000000011f8c1e47: mov %r10,0x2a8(%r15)
0x000000011f8c1e4e: xor %r10,%r10
0x000000011f8c1e51: mov %r10,0x2b0(%r15)
0x000000011f8c1e58: mov %rax,%rsi
0x000000011f8c1e5b: movabs $0x795926248,%rax ; {oop(a 'java/lang/Class' = 'com/hx/test05/Test03SingletonPrintAssembly')}
0x000000011f8c1e65: lea 0x28(%rsp),%rax
0x000000011f8c1e6a: mov 0x8(%rax),%rdi
0x000000011f8c1e6e: mov (%rdi),%rdx
0x000000011f8c1e71: and $0x7,%rdx
0x000000011f8c1e75: cmp $0x5,%rdx
0x000000011f8c1e79: je 0x000000011f8c1e96
0x000000011f8c1e7f: mov (%rax),%rdx
0x000000011f8c1e82: test %rdx,%rdx
0x000000011f8c1e85: je 0x000000011f8c1e96
0x000000011f8c1e8b: lock cmpxchg %rdx,(%rdi)
0x000000011f8c1e90: jne 0x000000011f8c1ef8 ;*monitorexit
; - com.hx.test05.Test03SingletonPrintAssembly::getInstance@34 (line 30)
0x000000011f8c1e96: mov %rsi,%rax ; OopMap{rsi=Oop rax=Oop off=761}
;*athrow
; - com.hx.test05.Test03SingletonPrintAssembly::getInstance@36 (line 30)
0x000000011f8c1e99: movabs $0x11f8c1e99,%rdx ; {section_word}
0x000000011f8c1ea3: callq 0x000000011f82e2a0 ; {runtime_call}
0x000000011f8c1ea8: nop
// $rsp+0x8 = method
// $rsp = $0xffffffffffffffff
0x000000011f8c1ea9: mov %rax,0x8(%rsp)
0x000000011f8c1eae: movq $0xffffffffffffffff,(%rsp)
0x000000011f8c1eb6: callq 0x000000011f8c05a0 ; OopMap{off=795}
;*synchronization entry
; - com.hx.test05.Test03SingletonPrintAssembly::getInstance@-1 (line 25)
; {runtime_call}
0x000000011f8c1ebb: jmpq 0x000000011f8c1bdb
0x000000011f8c1ec0: callq 0x000000011f8bbe00 ; OopMap{rdx=Oop off=805}
;*monitorenter
; - com.hx.test05.Test03SingletonPrintAssembly::getInstance@10 (line 26)
; {runtime_call}
// InterceptorRuntime::monitorenter
0x000000011f8c1ec5: mov %rdx,0x8(%rsp)
0x000000011f8c1eca: mov %rsi,(%rsp)
0x000000011f8c1ece: callq 0x000000011f8be7e0 ; OopMap{rdx=Oop [48]=Oop off=819}
;*monitorenter
; - com.hx.test05.Test03SingletonPrintAssembly::getInstance@10 (line 26)
; {runtime_call}
0x000000011f8c1ed3: jmpq 0x000000011f8c1cf6
// new Test03SingletonPrintAssembly
0x000000011f8c1ed8: mov %rdx,%rdx
0x000000011f8c1edb: callq 0x000000011f8bc560 ; OopMap{[48]=Oop off=832}
;*new ; - com.hx.test05.Test03SingletonPrintAssembly::getInstance@17 (line 28)
; {runtime_call}
0x000000011f8c1ee0: jmpq 0x000000011f8c1d7e
// InterceptorRuntime::monitorexit
0x000000011f8c1ee5: lea 0x28(%rsp),%rax
0x000000011f8c1eea: mov %rax,(%rsp)
0x000000011f8c1eee: callq 0x000000011f8bec20 ; {runtime_call}
0x000000011f8c1ef3: jmpq 0x000000011f8c1e10
// InterceptorRuntime::monitorexit goto exHandle
0x000000011f8c1ef8: lea 0x28(%rsp),%rax
0x000000011f8c1efd: mov %rax,(%rsp)
0x000000011f8c1f01: callq 0x000000011f8bec20 ; {runtime_call}
0x000000011f8c1f06: jmp 0x000000011f8c1e96
0x000000011f8c1f08: nop
0x000000011f8c1f09: nop
0x000000011f8c1f0a: mov 0x2a8(%r15),%rax
0x000000011f8c1f11: movabs $0x0,%r10
0x000000011f8c1f1b: mov %r10,0x2a8(%r15)
0x000000011f8c1f22: movabs $0x0,%r10
0x000000011f8c1f2c: mov %r10,0x2b0(%r15)
0x000000011f8c1f33: add $0x40,%rsp
0x000000011f8c1f37: pop %rbp
0x000000011f8c1f38: jmpq 0x000000011f82e960 ; {runtime_call}
0x000000011f8c1f3d: hlt
0x000000011f8c1f3e: hlt
0x000000011f8c1f3f: hlt
相关的代码 block, 我已经添加了相关的注释, 然后 method_data 部分的数据分析 应该是埋下的坑, 后面再回来填
首先 需要详细看下 上面的这部分的汇编, 并且 参照一下 测试用例的字节码
这里面将一部分的过程 内联进来了, 比如 monitorenter, monitorexit 的处理, 分配 Test03SingletonPrintAssembly 对象的处理 等等
所以 汇编代码 膨胀了很多, 不过 这都是 vm 优化的结果呀, 前辈们的心血的产物
并且这里 如果没得 monitorenter, monitorexit 的相关汇编代码的基础, 这里会看的很懵, 传送门 : 09 给对象添加偏向锁的调试
1. instance 不为空
2. instance 为空, 进入同步代码块, instance 不为空
3. instance 为空, 进入同步代码块, instance 为空
4. 偏向锁进入同步代码块
5. 轻量级锁进入同步代码块
6. 重量级锁进入同步代码块
7. Test03SingletonPrintAssembly 的空间的分配
// rax = Test03SingletonPrintAssembly.INSTANCE
0x000000011f8c1bdb: movabs $0x795926248,%rax ; {oop(a 'java/lang/Class' = 'com/hx/test05/Test03SingletonPrintAssembly')}
0x000000011f8c1be5: mov 0x68(%rax),%eax
0x000000011f8c1be8: shl $0x3,%rax ;*getstatic INSTANCE
; - com.hx.test05.Test03SingletonPrintAssembly::getInstance@0 (line 25)
// if(Test03SingletonPrintAssembly.INSTANCE != null) goto 0x000000011f8c1e20;
0x000000011f8c1bec: cmp $0x0,%rax
0x000000011f8c1bf0: movabs $0x1172d7108,%rax ; {metadata(method data for {method} {0x00000001172d6fb0} 'getInstance' '()Lcom/hx/test05/Test03SingletonPrintAssembly;' in 'com/hx/test05/Test03SingletonPrintAssembly')}
0x000000011f8c1bfa: movabs $0x108,%rdx
0x000000011f8c1c04: jne 0x000000011f8c1c14
0x000000011f8c1c0a: movabs $0x118,%rdx
// method_data[0x108] += 1 // method_data->_eflags
0x000000011f8c1c14: mov (%rax,%rdx,1),%rsi
0x000000011f8c1c18: lea 0x1(%rsi),%rsi
0x000000011f8c1c1c: mov %rsi,(%rax,%rdx,1)
0x000000011f8c1c20: jne 0x000000011f8c1e20 ;*ifnonnull
; - com.hx.test05.Test03SingletonPrintAssembly::getInstance@3 (line 25)
// rax = Test03SingletonPrintAssembly.INSTANCE
0x000000011f8c1e20: movabs $0x795926248,%rax ; {oop(a 'java/lang/Class' = 'com/hx/test05/Test03SingletonPrintAssembly')}
0x000000011f8c1e2a: mov 0x68(%rax),%eax
0x000000011f8c1e2d: shl $0x3,%rax ;*getstatic INSTANCE
; - com.hx.test05.Test03SingletonPrintAssembly::getInstance@37 (line 33)
// 销毁栈帧
0x000000011f8c1e31: add $0x40,%rsp
0x000000011f8c1e35: pop %rbp
0x000000011f8c1e36: test %eax,-0xf95ad3c(%rip) # 0x000000010ff67100
; {poll_return}
0x000000011f8c1e3c: retq ;*areturn
; - com.hx.test05.Test03SingletonPrintAssembly::getInstance@40 (line 33)
如果 instance 不为空, 那么直接 加载到 rax 里面 然后销毁栈帧 返回
// rax = Test03SingletonPrintAssembly.INSTANCE
0x000000011f8c1bdb: movabs $0x795926248,%rax ; {oop(a 'java/lang/Class' = 'com/hx/test05/Test03SingletonPrintAssembly')}
0x000000011f8c1be8: shl $0x3,%rax ;*getstatic INSTANCE
; - com.hx.test05.Test03SingletonPrintAssembly::getInstance@0 (line 25)
0x000000011f8c1be5: mov 0x68(%rax),%eax
// if(Test03SingletonPrintAssembly.INSTANCE != null) goto 0x000000011f8c1e20;
0x000000011f8c1bec: cmp $0x0,%rax
0x000000011f8c1bf0: movabs $0x1172d7108,%rax ; {metadata(method data for {method} {0x00000001172d6fb0} 'getInstance' '()Lcom/hx/test05/Test03SingletonPrintAssembly;' in 'com/hx/test05/Test03SingletonPrintAssembly')}
0x000000011f8c1bfa: movabs $0x108,%rdx
0x000000011f8c1c04: jne 0x000000011f8c1c14
0x000000011f8c1c0a: movabs $0x118,%rdx
// method_data[0x108] += 1 // method_data->_eflags
0x000000011f8c1c14: mov (%rax,%rdx,1),%rsi
0x000000011f8c1c18: lea 0x1(%rsi),%rsi
0x000000011f8c1c1c: mov %rsi,(%rax,%rdx,1)
0x000000011f8c1c20: jne 0x000000011f8c1e20 ;*ifnonnull
; - com.hx.test05.Test03SingletonPrintAssembly::getInstance@3 (line 25)
// 0x000000011f8c1c26 : 加锁相关代码
// rdx = Test03SingletonPrintAssembly.INSTANCE
0x000000011f8c1cf6: movabs $0x795926248,%rdx ; {oop(a 'java/lang/Class' = 'com/hx/test05/Test03SingletonPrintAssembly')}
0x000000011f8c1d00: mov 0x68(%rdx),%edx
0x000000011f8c1d03: shl $0x3,%rdx ;*getstatic INSTANCE
; - com.hx.test05.Test03SingletonPrintAssembly::getInstance@11 (line 27)
// if(Test03SingletonPrintAssembly.INSTANCE != null) goto 0x000000011f8c1dd5; // monitorexit(已经添加了锁)
0x000000011f8c1d07: cmp $0x0,%rdx
0x000000011f8c1d0b: movabs $0x1172d7108,%rdx ; {metadata(method data for {method} {0x00000001172d6fb0} 'getInstance' '()Lcom/hx/test05/Test03SingletonPrintAssembly;' in 'com/hx/test05/Test03SingletonPrintAssembly')}
0x000000011f8c1d15: movabs $0x128,%rsi
0x000000011f8c1d1f: jne 0x000000011f8c1d2f
0x000000011f8c1d25: movabs $0x138,%rsi
0x000000011f8c1d2f: mov (%rdx,%rsi,1),%rdi
0x000000011f8c1d33: lea 0x1(%rdi),%rdi
0x000000011f8c1d37: mov %rdi,(%rdx,%rsi,1)
0x000000011f8c1d3b: jne 0x000000011f8c1dd5 ;*ifnonnull
; - com.hx.test05.Test03SingletonPrintAssembly::getInstance@14 (line 27)
// 0x000000011f8c1dd5 : 解锁相关代码, 解锁相关代码之后 便是获取 Test03SingletonPrintAssembly.INSTANCE 返回
// rax = Test03SingletonPrintAssembly.INSTANCE
0x000000011f8c1e20: movabs $0x795926248,%rax ; {oop(a 'java/lang/Class' = 'com/hx/test05/Test03SingletonPrintAssembly')}
0x000000011f8c1e2a: mov 0x68(%rax),%eax
0x000000011f8c1e2d: shl $0x3,%rax ;*getstatic INSTANCE
; - com.hx.test05.Test03SingletonPrintAssembly::getInstance@37 (line 33)
// 销毁栈帧
0x000000011f8c1e31: add $0x40,%rsp
0x000000011f8c1e35: pop %rbp
0x000000011f8c1e36: test %eax,-0xf95ad3c(%rip) # 0x000000010ff67100
; {poll_return}
0x000000011f8c1e3c: retq ;*areturn
; - com.hx.test05.Test03SingletonPrintAssembly::getInstance@40 (line 33)
第一个检查 instance 为空, 然后进行 monitorenter, 第二个检查 instance 不为空, 然后 走 monitorexit, 然后获取 INSTANCE 返回
// rax = Test03SingletonPrintAssembly.INSTANCE
0x000000011f8c1bdb: movabs $0x795926248,%rax ; {oop(a 'java/lang/Class' = 'com/hx/test05/Test03SingletonPrintAssembly')}
0x000000011f8c1be8: shl $0x3,%rax ;*getstatic INSTANCE
; - com.hx.test05.Test03SingletonPrintAssembly::getInstance@0 (line 25)
0x000000011f8c1be5: mov 0x68(%rax),%eax
// if(Test03SingletonPrintAssembly.INSTANCE != null) goto 0x000000011f8c1e20;
0x000000011f8c1bec: cmp $0x0,%rax
0x000000011f8c1bf0: movabs $0x1172d7108,%rax ; {metadata(method data for {method} {0x00000001172d6fb0} 'getInstance' '()Lcom/hx/test05/Test03SingletonPrintAssembly;' in 'com/hx/test05/Test03SingletonPrintAssembly')}
0x000000011f8c1bfa: movabs $0x108,%rdx
0x000000011f8c1c04: jne 0x000000011f8c1c14
0x000000011f8c1c0a: movabs $0x118,%rdx
// method_data[0x108] += 1 // method_data->_eflags
0x000000011f8c1c14: mov (%rax,%rdx,1),%rsi
0x000000011f8c1c18: lea 0x1(%rsi),%rsi
0x000000011f8c1c1c: mov %rsi,(%rax,%rdx,1)
0x000000011f8c1c20: jne 0x000000011f8c1e20 ;*ifnonnull
; - com.hx.test05.Test03SingletonPrintAssembly::getInstance@3 (line 25)
// 0x000000011f8c1c26 : 加锁相关代码
// rdx = Test03SingletonPrintAssembly.INSTANCE
0x000000011f8c1cf6: movabs $0x795926248,%rdx ; {oop(a 'java/lang/Class' = 'com/hx/test05/Test03SingletonPrintAssembly')}
0x000000011f8c1d00: mov 0x68(%rdx),%edx
0x000000011f8c1d03: shl $0x3,%rdx ;*getstatic INSTANCE
; - com.hx.test05.Test03SingletonPrintAssembly::getInstance@11 (line 27)
// if(Test03SingletonPrintAssembly.INSTANCE != null) goto 0x000000011f8c1dd5; // monitorexit(已经添加了锁)
0x000000011f8c1d07: cmp $0x0,%rdx
0x000000011f8c1d0b: movabs $0x1172d7108,%rdx ; {metadata(method data for {method} {0x00000001172d6fb0} 'getInstance' '()Lcom/hx/test05/Test03SingletonPrintAssembly;' in 'com/hx/test05/Test03SingletonPrintAssembly')}
0x000000011f8c1d15: movabs $0x128,%rsi
0x000000011f8c1d1f: jne 0x000000011f8c1d2f
0x000000011f8c1d25: movabs $0x138,%rsi
0x000000011f8c1d2f: mov (%rdx,%rsi,1),%rdi
0x000000011f8c1d33: lea 0x1(%rdi),%rdi
0x000000011f8c1d37: mov %rdi,(%rdx,%rsi,1)
0x000000011f8c1d3b: jne 0x000000011f8c1dd5 ;*ifnonnull
; - com.hx.test05.Test03SingletonPrintAssembly::getInstance@14 (line 27)
// 0x000000011f8c1d41 : INSTANCE = new Test03SingletonPrintAssembly(), 创建对象, 调用构造方法, 保存对象
// 0x000000011f8c1dd5 : 解锁相关代码, 解锁相关代码之后 便是获取 Test03SingletonPrintAssembly.INSTANCE 返回
// rax = Test03SingletonPrintAssembly.INSTANCE
0x000000011f8c1e20: movabs $0x795926248,%rax ; {oop(a 'java/lang/Class' = 'com/hx/test05/Test03SingletonPrintAssembly')}
0x000000011f8c1e2a: mov 0x68(%rax),%eax
0x000000011f8c1e2d: shl $0x3,%rax ;*getstatic INSTANCE
; - com.hx.test05.Test03SingletonPrintAssembly::getInstance@37 (line 33)
// 销毁栈帧
0x000000011f8c1e31: add $0x40,%rsp
0x000000011f8c1e35: pop %rbp
0x000000011f8c1e36: test %eax,-0xf95ad3c(%rip) # 0x000000010ff67100
; {poll_return}
0x000000011f8c1e3c: retq ;*areturn
; - com.hx.test05.Test03SingletonPrintAssembly::getInstance@40 (line 33)
// ($rsp) + 0x30 = Test03SingletonPrintAssembly.class
// rsi = BasicLockObject
// BasicLockObject.obj = Test03SingletonPrintAssembly.class
0x000000011f8c1c26: movabs $0x795926248,%rdx ; {oop(a 'java/lang/Class' = 'com/hx/test05/Test03SingletonPrintAssembly')}
0x000000011f8c1c30: lea 0x28(%rsp),%rsi
0x000000011f8c1c35: mov %rdx,0x8(%rsi)
// if(!Test03SingletonPrintAssembly.class.has_bias_pattern()) goto 0x000000011f8c1cce;
0x000000011f8c1c39: mov (%rdx),%rax ; implicit exception: dispatches to 0x000000011f8c1ec0
0x000000011f8c1c3c: mov %rax,%rdi
0x000000011f8c1c3f: and $0x7,%rdi
0x000000011f8c1c43: cmp $0x5,%rdi
0x000000011f8c1c47: jne 0x000000011f8c1cce
// mark 掉除了 age 之外的部分, 进行比较, 如果相等 则是偏向锁重入, 直接加锁成功
0x000000011f8c1c4d: mov 0x8(%rdx),%edi
0x000000011f8c1c50: shl $0x3,%rdi
0x000000011f8c1c54: mov 0xa8(%rdi),%rdi
0x000000011f8c1c5b: or %r15,%rdi
0x000000011f8c1c5e: xor %rax,%rdi
0x000000011f8c1c61: and $0xffffffffffffff87,%rdi
0x000000011f8c1c65: je 0x000000011f8c1cf6
// if (lockBits != 0) goto try_revoke_bias
0x000000011f8c1c6b: test $0x7,%rdi
0x000000011f8c1c72: jne 0x000000011f8c1cbb
// if (epoch != 0) goto try_rebias
0x000000011f8c1c74: test $0x300,%rdi
0x000000011f8c1c7b: jne 0x000000011f8c1c9a
// epoch is valid
0x000000011f8c1c7d: and $0x37f,%rax
0x000000011f8c1c84: mov %rax,%rdi
0x000000011f8c1c87: or %r15,%rdi
0x000000011f8c1c8a: lock cmpxchg %rdi,(%rdx)
0x000000011f8c1c8f: jne 0x000000011f8c1ec5
0x000000011f8c1c95: jmpq 0x000000011f8c1cf6
// rebias
0x000000011f8c1c9a: mov 0x8(%rdx),%edi
0x000000011f8c1c9d: shl $0x3,%rdi
0x000000011f8c1ca1: mov 0xa8(%rdi),%rdi
0x000000011f8c1ca8: or %r15,%rdi
0x000000011f8c1cab: lock cmpxchg %rdi,(%rdx)
0x000000011f8c1cb0: jne 0x000000011f8c1ec5
0x000000011f8c1cb6: jmpq 0x000000011f8c1cf6
// ($rsp) + 0x30 = Test03SingletonPrintAssembly.class
// rsi = BasicLockObject
// BasicLockObject.obj = Test03SingletonPrintAssembly.class
0x000000011f8c1c26: movabs $0x795926248,%rdx ; {oop(a 'java/lang/Class' = 'com/hx/test05/Test03SingletonPrintAssembly')}
0x000000011f8c1c30: lea 0x28(%rsp),%rsi
0x000000011f8c1c35: mov %rdx,0x8(%rsi)
// if(!Test03SingletonPrintAssembly.class.has_bias_pattern()) goto 0x000000011f8c1cce;
0x000000011f8c1c39: mov (%rdx),%rax ; implicit exception: dispatches to 0x000000011f8c1ec0
0x000000011f8c1c3c: mov %rax,%rdi
0x000000011f8c1c3f: and $0x7,%rdi
0x000000011f8c1c43: cmp $0x5,%rdi
0x000000011f8c1c47: jne 0x000000011f8c1cce
// mark 掉除了 age 之外的部分, 进行比较, 如果相等 则是偏向锁重入, 直接加锁成功
0x000000011f8c1c4d: mov 0x8(%rdx),%edi
0x000000011f8c1c50: shl $0x3,%rdi
0x000000011f8c1c54: mov 0xa8(%rdi),%rdi
0x000000011f8c1c5b: or %r15,%rdi
0x000000011f8c1c5e: xor %rax,%rdi
0x000000011f8c1c61: and $0xffffffffffffff87,%rdi
0x000000011f8c1c65: je 0x000000011f8c1cf6
// if (lockBits != 0) goto try_revoke_bias
0x000000011f8c1c6b: test $0x7,%rdi
0x000000011f8c1c72: jne 0x000000011f8c1cbb
// if (epoch != 0) goto try_rebias
0x000000011f8c1c74: test $0x300,%rdi
0x000000011f8c1c7b: jne 0x000000011f8c1c9a
// epoch is valid
0x000000011f8c1c7d: and $0x37f,%rax
0x000000011f8c1c84: mov %rax,%rdi
0x000000011f8c1c87: or %r15,%rdi
0x000000011f8c1c8a: lock cmpxchg %rdi,(%rdx)
0x000000011f8c1c8f: jne 0x000000011f8c1ec5
0x000000011f8c1c95: jmpq 0x000000011f8c1cf6
// rebias
0x000000011f8c1c9a: mov 0x8(%rdx),%edi
0x000000011f8c1c9d: shl $0x3,%rdi
0x000000011f8c1ca1: mov 0xa8(%rdi),%rdi
0x000000011f8c1ca8: or %r15,%rdi
0x000000011f8c1cab: lock cmpxchg %rdi,(%rdx)
0x000000011f8c1cb0: jne 0x000000011f8c1ec5
0x000000011f8c1cb6: jmpq 0x000000011f8c1cf6
// revoke
0x000000011f8c1cbb: mov 0x8(%rdx),%edi
0x000000011f8c1cbe: shl $0x3,%rdi
0x000000011f8c1cc2: mov 0xa8(%rdi),%rdi
0x000000011f8c1cc9: lock cmpxchg %rdi,(%rdx)
// 加轻量级锁
0x000000011f8c1cce: mov (%rdx),%rax
0x000000011f8c1cd1: or $0x1,%rax
0x000000011f8c1cd5: mov %rax,(%rsi)
0x000000011f8c1cd8: lock cmpxchg %rsi,(%rdx)
0x000000011f8c1cdd: je 0x000000011f8c1cf6
// 轻量级锁重入
0x000000011f8c1ce3: sub %rsp,%rax
0x000000011f8c1ce6: and $0xfffffffffffff007,%rax
0x000000011f8c1ced: mov %rax,(%rsi)
// ($rsp) + 0x30 = Test03SingletonPrintAssembly.class
// rsi = BasicLockObject
// BasicLockObject.obj = Test03SingletonPrintAssembly.class
0x000000011f8c1c26: movabs $0x795926248,%rdx ; {oop(a 'java/lang/Class' = 'com/hx/test05/Test03SingletonPrintAssembly')}
0x000000011f8c1c30: lea 0x28(%rsp),%rsi
0x000000011f8c1c35: mov %rdx,0x8(%rsi)
// if(!Test03SingletonPrintAssembly.class.has_bias_pattern()) goto 0x000000011f8c1cce;
0x000000011f8c1c39: mov (%rdx),%rax ; implicit exception: dispatches to 0x000000011f8c1ec0
0x000000011f8c1c3c: mov %rax,%rdi
0x000000011f8c1c3f: and $0x7,%rdi
0x000000011f8c1c43: cmp $0x5,%rdi
0x000000011f8c1c47: jne 0x000000011f8c1cce
// mark 掉除了 age 之外的部分, 进行比较, 如果相等 则是偏向锁重入, 直接加锁成功
0x000000011f8c1c4d: mov 0x8(%rdx),%edi
0x000000011f8c1c50: shl $0x3,%rdi
0x000000011f8c1c54: mov 0xa8(%rdi),%rdi
0x000000011f8c1c5b: or %r15,%rdi
0x000000011f8c1c5e: xor %rax,%rdi
0x000000011f8c1c61: and $0xffffffffffffff87,%rdi
0x000000011f8c1c65: je 0x000000011f8c1cf6
// if (lockBits != 0) goto try_revoke_bias
0x000000011f8c1c6b: test $0x7,%rdi
0x000000011f8c1c72: jne 0x000000011f8c1cbb
// if (epoch != 0) goto try_rebias
0x000000011f8c1c74: test $0x300,%rdi
0x000000011f8c1c7b: jne 0x000000011f8c1c9a
// epoch is valid
0x000000011f8c1c7d: and $0x37f,%rax
0x000000011f8c1c84: mov %rax,%rdi
0x000000011f8c1c87: or %r15,%rdi
0x000000011f8c1c8a: lock cmpxchg %rdi,(%rdx)
0x000000011f8c1c8f: jne 0x000000011f8c1ec5
0x000000011f8c1c95: jmpq 0x000000011f8c1cf6
// rebias
0x000000011f8c1c9a: mov 0x8(%rdx),%edi
0x000000011f8c1c9d: shl $0x3,%rdi
0x000000011f8c1ca1: mov 0xa8(%rdi),%rdi
0x000000011f8c1ca8: or %r15,%rdi
0x000000011f8c1cab: lock cmpxchg %rdi,(%rdx)
0x000000011f8c1cb0: jne 0x000000011f8c1ec5
0x000000011f8c1cb6: jmpq 0x000000011f8c1cf6
// revoke
0x000000011f8c1cbb: mov 0x8(%rdx),%edi
0x000000011f8c1cbe: shl $0x3,%rdi
0x000000011f8c1cc2: mov 0xa8(%rdi),%rdi
0x000000011f8c1cc9: lock cmpxchg %rdi,(%rdx)
// 加轻量级锁
0x000000011f8c1cce: mov (%rdx),%rax
0x000000011f8c1cd1: or $0x1,%rax
0x000000011f8c1cd5: mov %rax,(%rsi)
0x000000011f8c1cd8: lock cmpxchg %rsi,(%rdx)
0x000000011f8c1cdd: je 0x000000011f8c1cf6
// 轻量级锁重入
0x000000011f8c1ce3: sub %rsp,%rax
0x000000011f8c1ce6: and $0xfffffffffffff007,%rax
0x000000011f8c1ced: mov %rax,(%rsi)
// 加重量级锁
0x000000011f8c1cf0: jne 0x000000011f8c1ec5 ;*monitorenter
; - com.hx.test05.Test03SingletonPrintAssembly::getInstance@10 (line 26)
// InterceptorRuntime::monitorenter
0x000000011f8c1ec5: mov %rdx,0x8(%rsp)
0x000000011f8c1eca: mov %rsi,(%rsp)
0x000000011f8c1ece: callq 0x000000011f8be7e0 ; OopMap{rdx=Oop [48]=Oop off=819}
;*monitorenter
; - com.hx.test05.Test03SingletonPrintAssembly::getInstance@10 (line 26)
; {runtime_call}
0x000000011f8c1ed3: jmpq 0x000000011f8c1cf6
// rax = 0x60(%r15) = &(thread->_tlab)._top
// 0x70(%r15) = &(thread->_tlab)._end
// if((thread->_tlab)._end < ((thread->_tlab)._top + 0x10)) goto 0x000000011f8c1ed8;
0x000000011f8c1d41: movabs $0x7c0061aa0,%rdx ; {metadata('com/hx/test05/Test03SingletonPrintAssembly')}
0x000000011f8c1d4b: mov 0x60(%r15),%rax
0x000000011f8c1d4f: lea 0x10(%rax),%rdi
0x000000011f8c1d53: cmp 0x70(%r15),%rdi
0x000000011f8c1d57: ja 0x000000011f8c1ed8
// (thread->_tlab)._top = (thread->_tlab)._top + 0x10)
0x000000011f8c1d5d: mov %rdi,0x60(%r15)
// oop.mark = Test03SingletonPrintAssembly.class.prototype_header
0x000000011f8c1d61: mov 0xa8(%rdx),%rcx
0x000000011f8c1d68: mov %rcx,(%rax)
// oop.klass = Test03SingletonPrintAssembly.class
0x000000011f8c1d6b: mov %rdx,%rcx
0x000000011f8c1d6e: shr $0x3,%rcx
0x000000011f8c1d72: mov %ecx,0x8(%rax)
// oop.padding = 0
0x000000011f8c1d75: xor %rcx,%rcx
0x000000011f8c1d78: mov %ecx,0xc(%rax)
// rcx = 0
0x000000011f8c1d7b: xor %rcx,%rcx ;*new ; - com.hx.test05.Test03SingletonPrintAssembly::getInstance@17 (line 28)
public static Test03SingletonPrintAssembly getInstance() {
if(INSTANCE == null) {
synchronized (Test03SingletonPrintAssembly.class) {
if(INSTANCE == null) {
INSTANCE = new Test03SingletonPrintAssembly();
}
}
}
synchronized (INSTANCE) {
}
return INSTANCE;
}
若是 我们对 getInstance 方法进行了如下的调整, 然后 在对比一下, 会增加 关于 synchronized(INSTANCE) 的这部分的同步代码
// rdx = Test03SingletonPrintAssembly.INSTANCE
0x00000001094f7320: movabs $0x7959262f0,%rax ; {oop(a 'java/lang/Class' = 'com/hx/test05/Test03SingletonPrintAssembly')}
0x00000001094f732a: mov 0x68(%rax),%edx
0x00000001094f732d: shl $0x3,%rdx ;*getstatic INSTANCE
; - com.hx.test05.Test03SingletonPrintAssembly::getInstance@37 (line 33)
// BasicLockObject.obj = Test03SingletonPrintAssembly.INSTANCE
0x00000001094f7331: lea 0x28(%rsp),%rsi
0x00000001094f7336: mov %rdx,0x8(%rsi)
// if(!BasicLockObject.obj) goto 0x000000011f8c1cce;
0x00000001094f733a: mov (%rdx),%rax ; implicit exception: dispatches to 0x00000001094f7510
0x00000001094f733d: mov %rax,%rdi
0x00000001094f7340: and $0x7,%rdi
0x00000001094f7344: cmp $0x5,%rdi
0x00000001094f7348: jne 0x00000001094f73cf
// mark 掉除了 age 之外的部分, 进行比较, 如果相等 则是偏向锁重入, 直接加锁成功
0x00000001094f734e: mov 0x8(%rdx),%edi
0x00000001094f7351: shl $0x3,%rdi
0x00000001094f7355: mov 0xa8(%rdi),%rdi
0x00000001094f735c: or %r15,%rdi
0x00000001094f735f: xor %rax,%rdi
0x00000001094f7362: and $0xffffffffffffff87,%rdi
0x00000001094f7366: je 0x00000001094f73f7
// if (lockBits != 0) goto try_revoke_bias
0x00000001094f736c: test $0x7,%rdi
0x00000001094f7373: jne 0x00000001094f73bc
// if (epoch != 0) goto try_rebias
0x00000001094f7375: test $0x300,%rdi
0x00000001094f737c: jne 0x00000001094f739b
// epoch is valid
0x00000001094f737e: and $0x37f,%rax
0x00000001094f7385: mov %rax,%rdi
0x00000001094f7388: or %r15,%rdi
0x00000001094f738b: lock cmpxchg %rdi,(%rdx)
0x00000001094f7390: jne 0x00000001094f7515
0x00000001094f7396: jmpq 0x00000001094f73f7
// rebias
0x00000001094f739b: mov 0x8(%rdx),%edi
0x00000001094f739e: shl $0x3,%rdi
0x00000001094f73a2: mov 0xa8(%rdi),%rdi
0x00000001094f73a9: or %r15,%rdi
0x00000001094f73ac: lock cmpxchg %rdi,(%rdx)
0x00000001094f73b1: jne 0x00000001094f7515
0x00000001094f73b7: jmpq 0x00000001094f73f7
// revoke
0x00000001094f73bc: mov 0x8(%rdx),%edi
0x00000001094f73bf: shl $0x3,%rdi
0x00000001094f73c3: mov 0xa8(%rdi),%rdi
0x00000001094f73ca: lock cmpxchg %rdi,(%rdx)
// 加轻量级锁
0x00000001094f73cf: mov (%rdx),%rax
0x00000001094f73d2: or $0x1,%rax
0x00000001094f73d6: mov %rax,(%rsi)
0x00000001094f73d9: lock cmpxchg %rsi,(%rdx)
0x00000001094f73de: je 0x00000001094f73f7
// 轻量级锁重入的情况
0x00000001094f73e4: sub %rsp,%rax
0x00000001094f73e7: and $0xfffffffffffff007,%rax
0x00000001094f73ee: mov %rax,(%rsi)
// 加重量级锁
0x00000001094f73f1: jne 0x00000001094f7515 ;*monitorenter
; - com.hx.test05.Test03SingletonPrintAssembly::getInstance@42 (line 33)
// rsi = BasicLockObject.obj
0x00000001094f73f7: lea 0x28(%rsp),%rax
0x00000001094f73fc: mov 0x8(%rax),%rsi
// if(BasicLockObject.obj.has_bias_pattern()) goto 0x00000001094f7428;
0x00000001094f7400: mov (%rsi),%rdx
0x00000001094f7403: and $0x7,%rdx
0x00000001094f7407: cmp $0x5,%rdx
0x00000001094f740b: je 0x00000001094f7428
// 轻量级锁重入
0x00000001094f7411: mov (%rax),%rdx
0x00000001094f7414: test %rdx,%rdx
0x00000001094f7417: je 0x00000001094f7428
// 轻量级锁解锁
0x00000001094f741d: lock cmpxchg %rdx,(%rsi)
// 走 InterpreterRuntime::monitorexit
0x00000001094f7422: jne 0x00000001094f7528 ;*monitorexit
; - com.hx.test05.Test03SingletonPrintAssembly::getInstance@44 (line 35)
0x00000001094f7428: movabs $0x107c75138,%rax ; {metadata(method data for {method} {0x0000000107c74fd0} 'getInstance' '()Lcom/hx/test05/Test03SingletonPrintAssembly;' in 'com/hx/test05/Test03SingletonPrintAssembly')}
0x00000001094f7432: incl 0x170(%rax) ;*goto
; - com.hx.test05.Test03SingletonPrintAssembly::getInstance@45 (line 35)
1. 另外还有一个细节是 monitorexit 部分的代码 没有清理 BasicLockObject.obj, 呵呵 可能是 削除掉了吧
2. 对比 INSTANCE 是否有 volatile 的编译差异, 会发现 有vilatile 的时候, putstatic 之后会添加一句(这个要结合 lock 指令, happens before 等等来理解)
0x00000001161f0310: lock addl $0x0,(%rsp)
3. 针对上面的 getInstance 的调整之后生成的汇编代码, 我们会发现两个细节, 第一个就是 这是一个无用的同步代码块, 似乎是没有被削除啊(可能是优化级别不够吧), 另外一个是 哈哈 我的这个调整其实是主要是 想测试让 compiler 在 monitorexit 的地方吧 BasicLockObject = null 生成出来, 但是 这里是直接复用了 BasicLockObject 呀
4. 从以上的相关代码呀, 流程来看, 要读 PrintAssembly 的输出结果, 第一是要有一定的汇编基础, 第二是需要了解vm的相关数据存储方式, 第三是对于一些常见的内联的函数的汇编要经常读(比如这里的 monitorenter, moniterexit, new), 呵呵 路漫漫其修远兮
完
JVM执行篇:使用HSDIS插件分析JVM代码执行细节--转
17 PrintAssembly的汇编结果分析的HelloWorld
09 给对象添加偏向锁的调试