18 双检锁单例的PrintAssembly的汇编结果分析

前言

呵呵 接上一篇 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 给对象添加偏向锁的调试, 那么你会发现 给定的字节码 也有这两个 异常处理, 不过 因为文章的目的并不是讨论这两段异常代码添加的原因, 所以 就不用过多的纠结于此了 

 

 

PrintAssembly 输出结果

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 给对象添加偏向锁的调试

 

 

讨论一下几种case

1. instance 不为空 

2. instance 为空, 进入同步代码块, instance 不为空 

3. instance 为空, 进入同步代码块, instance 为空 

 

4. 偏向锁进入同步代码块 

5. 轻量级锁进入同步代码块 

6. 重量级锁进入同步代码块 

 

7. Test03SingletonPrintAssembly 的空间的分配 

 

 

1. instance 不为空 

  // 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 里面 然后销毁栈帧 返回 

 

 

2. instance 为空, 进入同步代码块, 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)

  // 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 返回 

 

 

3. instance 为空, 进入同步代码块, 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)

 

 

4. 偏向锁进入同步代码块 

  // ($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

 

 

5. 轻量级锁进入同步代码块 

  // ($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)

 

 

6. 重量级锁进入同步代码块 

  // ($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

 

 

7. Test03SingletonPrintAssembly 的空间的分配 

  // 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)

 

 

7. getInstance 调整增加同步代码块

  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 给对象添加偏向锁的调试

 

你可能感兴趣的:(11,HotspotVM,java,hotspotvm,assembly)