59 多线程环境普通变量作为标记循环不结束

Posted 蓝风9

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了59 多线程环境普通变量作为标记循环不结束相关的知识,希望对你有一定的参考价值。

前言

最近看到这篇例子的时候, [讨论] 内存可见性问题, 吧其中的 demo 拿到本地来跑 

居然 和楼主一样, testBasicType 这里面的这个子线程 居然 不结束了, 卧槽  我还以为 只是可能 用的时间稍微长一点 

哪知道 直接 无限期执行下去了, 然后 另外还有一个情况就是 加上了 -Xint, -Xcomp 都能够 完成 testBasicType 里面的线程的执行 

默认 啥都不加的情况 testBasicType 一直无限期的执行下去了 (-Xmixed)

呵呵 反正还是有很多神奇的地方, 也有很多 超出了我认知范畴的事情啊 

呵呵 不过还是需要记录一些东西, 毕竟有一些 直观的收货 

擦另外一件关键的事情就是, 我擦 尝试过使用 clion 来调试, 呵呵 结果 testBasicType 循环结束了 

然后 今早想到了这个 vm 执行模式 的相关的东西的时候, 我去掉了 -Xint 又尝试了一次, 擦 就能够复现了, 这样的话 那就更好了, 可以运行时 看下上下文的东西了 ^_^ 

在此之前是 使用 lldb 来调试, 中断的方式是通过 信号 

环境如下 

master:~ jerry$ uname -a
Darwin master.local 18.5.0 Darwin Kernel Version 18.5.0: Mon Mar 11 22:26:31 PDT 2019; root:xnu-4903.251.3~5/RELEASE_X86_64 x86_64
master:~ jerry$ java -version
java version "1.8.0_211"
Java(TM) SE Runtime Environment (build 1.8.0_211-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.211-b12, mixed mode)
master:~ jerry$ 

测试用例

package com.hx.test05;

import java.util.HashMap;

/**
 * Test22VisibleToStop
 *
 * @author Jerry.X.He <970655147@qq.com>
 * @version 1.0
 * @date 2020-05-04 17:33
 */
public class Test22VisibleToStop 

  private static boolean stop = false;
  private static volatile boolean v2stop = false;
  private static HashMap<String, Boolean> map2stop = new HashMap<String, Boolean>();

  // Test22VisibleToStop
  // 卧槽 显式加上 -Xint, -Xcomp 都能够停止, 啥都不加 停止不了,, 呵呵 好神奇啊
  // -XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly -XX:CompileCommand=dontinline,*Test22VisibleToStop$3.run -XX:CompileCommand=compileonly,*Test22VisibleToStop$3.run
  // 呵呵增加了一下 参数之后 直接就退出了
  // refer : https://hllvm-group.iteye.com/group/topic/39675
  public static void main(String[] args) throws Exception 

    testMap();
    testVolatile();
    testBasicType();
    testBasicTypeWithSync();

  

  //程序正常结束
  public static void testMap() throws InterruptedException
    map2stop.put("stop", Boolean.FALSE);
    new Thread()
      @Override
      public void run()
        int i=0;
        while (!map2stop.get("stop") )
          i++;
        
        System.out.println("map loop finish:"+i);
      
    .start();

    Thread.sleep(1000);
    map2stop.put("stop", Boolean.TRUE);
    Thread.sleep(1000);
    System.out.println("map main stop");
  

  //说明了volatile的开销
  public static void testVolatile() throws InterruptedException
    new Thread()
      @Override
      public void run()
        int i=0;
        while(!v2stop)
          i++;
        
        System.out.println("volatile loop finish:"+i);
      
    .start();

    Thread.sleep(1000);
    v2stop=true;
    Thread.sleep(1000);
    System.out.println("volatile main stop");
  

  //不可见,发生死循环
  public static void testBasicType() throws InterruptedException
    new Thread()
      @Override
      public void run()
        int i=0;
        while(!stop)
          i++;
        
        System.out.println("basic type loop finish:"+i);
      
    .start();

    Thread.sleep(1000);
    stop=true;
    Thread.sleep(1000);
    System.out.println("basic type main stop");
  

  //不可见,发生死循环
  public static void testBasicTypeWithSync() throws InterruptedException
    Object lock = new Object();
    new Thread()
      @Override
      public void run()
        int i=0;
        while(!stop)
          synchronized (lock) 
            i++;
          
        
        System.out.println("basic type with sync loop finish:"+i);
      
    .start();

    Thread.sleep(1000);
    synchronized (lock) 
      stop = true;
    
    Thread.sleep(1000);
    System.out.println("basic type with sync main stop");
  


基于 lldb 的调试

(lldb) thread list
Process 862 stopped
* thread #1: tid = 0x57c2, 0x00007fff7ef2622a libsystem_kernel.dylib`mach_msg_trap + 10, queue = 'com.apple.main-thread', stop reason = signal SIGQUIT
  thread #2: tid = 0x5832, 0x00007fff7ef289de libsystem_kernel.dylib`__ulock_wait + 10
  thread #4: tid = 0x5834, 0x00007fff7ef27bfe libsystem_kernel.dylib`__workq_kernreturn + 10
  thread #5: tid = 0x5835, 0x00007fff7ef2986a libsystem_kernel.dylib`__psynch_cvwait + 10
  thread #7: tid = 0x5840, 0x00007fff7ef2986a libsystem_kernel.dylib`__psynch_cvwait + 10
  thread #8: tid = 0x5841, 0x00007fff7ef2986a libsystem_kernel.dylib`__psynch_cvwait + 10
  thread #9: tid = 0x5842, 0x00007fff7ef2986a libsystem_kernel.dylib`__psynch_cvwait + 10
  thread #10: tid = 0x5843, 0x00007fff7ef2986a libsystem_kernel.dylib`__psynch_cvwait + 10
  thread #11: tid = 0x5844, 0x00007fff7ef2986a libsystem_kernel.dylib`__psynch_cvwait + 10
  thread #12: tid = 0x5845, 0x00007fff7ef2986a libsystem_kernel.dylib`__psynch_cvwait + 10
  thread #13: tid = 0x5846, 0x00007fff7ef2986a libsystem_kernel.dylib`__psynch_cvwait + 10
  thread #14: tid = 0x5847, 0x00007fff7ef2986a libsystem_kernel.dylib`__psynch_cvwait + 10
  thread #15: tid = 0x5848, 0x00007fff7ef2986a libsystem_kernel.dylib`__psynch_cvwait + 10
  thread #16: tid = 0x5849, 0x00007fff7ef2986a libsystem_kernel.dylib`__psynch_cvwait + 10, name = 'Java: Reference Handler'
  thread #17: tid = 0x584a, 0x00007fff7ef2986a libsystem_kernel.dylib`__psynch_cvwait + 10, name = 'Java: Finalizer'
  thread #18: tid = 0x584b, 0x00007fff7ef26266 libsystem_kernel.dylib`semaphore_wait_trap + 10, name = 'Java: Signal Dispatcher'
  thread #19: tid = 0x584c, 0x00007fff7ef2986a libsystem_kernel.dylib`__psynch_cvwait + 10, name = 'Java: C2 CompilerThread0'
  thread #20: tid = 0x584d, 0x00007fff7ef2986a libsystem_kernel.dylib`__psynch_cvwait + 10, name = 'Java: C2 CompilerThread1'
  thread #21: tid = 0x584e, 0x00007fff7ef2986a libsystem_kernel.dylib`__psynch_cvwait + 10, name = 'Java: C2 CompilerThread2'
  thread #22: tid = 0x584f, 0x00007fff7ef2986a libsystem_kernel.dylib`__psynch_cvwait + 10, name = 'Java: C1 CompilerThread3'
  thread #23: tid = 0x5850, 0x00007fff7ef2986a libsystem_kernel.dylib`__psynch_cvwait + 10, name = 'Java: Service Thread'
  thread #24: tid = 0x5851, 0x00007fff7ef2986a libsystem_kernel.dylib`__psynch_cvwait + 10
  thread #26: tid = 0x587c, 0x00000001048d2daa, name = 'Java: Thread-2'
(lldb) thread select 26
* thread #26, name = 'Java: Thread-2'
    frame #0: 0x00000001048d2daa
->  0x1048d2daa: jmp    0x1048d2da2
    0x1048d2dac: movl   $0xffffff86, %esi         ; imm = 0xFFFFFF86 
    0x1048d2db1: nop    
    0x1048d2db3: callq  0x1047fe6a0
(lldb) bt
* thread #26, name = 'Java: Thread-2'
  * frame #0: 0x00000001048d2daa
(lldb) re r
General Purpose Registers:
       rax = 0x0000000000000e0b
       rbx = 0x00000000000000b8
       rcx = 0x0000000000000000
       rdx = 0x00000000000e65f0
       rdi = 0x0000000000000000
       rsi = 0x0000000100100000
       rbp = 0x00000000e71bf269
       rsp = 0x0000700005b54960
        r8 = 0x0000000000000002
        r9 = 0x0000000000000000
       r10 = 0x0000000000000000
       r11 = 0x0000000000000003
       r12 = 0x0000000000000000
       r13 = 0x00000001048d2c10
       r14 = 0x0000700005b54980
       r15 = 0x0000000100847000
       rip = 0x00000001048d2daa
    rflags = 0x0000000000000246
        cs = 0x000000000000002b
        fs = 0x0000000000000000
        gs = 0x0000000000000000
(lldb) dis -s 0x1048d2d82 -c 0x20
    0x1048d2d82: movl   $0x3ce9b52, %edx          ; imm = 0x3CE9B52 
    0x1048d2d87: addl   %eax, (%rax)
    0x1048d2d89: addb   %al, (%rax)
    0x1048d2d8b: callq  *%r10
    0x1048d2d8e: movabsq $0x7955f36e0, %r10        ; imm = 0x7955F36E0 
    0x1048d2d98: movzbl 0x6c(%r10), %r10d
    0x1048d2d9d: testl  %r10d, %r10d
    0x1048d2da0: jne    0x1048d2dac
    0x1048d2da2: incl   %ebp
    0x1048d2da4: testl  %eax, -0x47d7daa(%rip)
->  0x1048d2daa: jmp    0x1048d2da2
    0x1048d2dac: movl   $0xffffff86, %esi         ; imm = 0xFFFFFF86 
    0x1048d2db1: nop    
    0x1048d2db3: callq  0x1047fe6a0
    0x1048d2db8: callq  0x103c8a904               ; os::breakpoint()
    0x1048d2dbd: callq  0x103c8a904               ; os::breakpoint()
    0x1048d2dc2: hlt    
    0x1048d2dc3: hlt    
    0x1048d2dc4: hlt    

这里的核心的代码 就比较直观了, 主要在箭头处 三行代码, 一行累增, 一行 safepoint 轮询, 一行 jump(死循环) 

incl ebp, 卧槽 bp 寄存器居然被分配来作为 计算的寄存器了, 哈哈 好神奇 

test %eax 0x1000FB000, safepoint 轮询

jmp    0x1048d2da2, 直接无条件的跳转到了 第一条指令, 构成了 死循环 

然后观察下 上面的 四条指令, 不就是类似于 if(!xxx.xx) goto $addr; 这种形式么? 

那么 0x7955f36e0 是啥呢?, 根据猜测 应该是 Test22VisibleToStop.class, 从业务代码的角度来看  

哎 但是这里只能查看 内存大的信息, 要去解码内存里面的信息 又太麻烦了, 呵呵 怎么办呢 ? 

用 clion 来吧, 或者 基于 fastdebug 版本的 jdk9 来进行 lldb 的调试 

基于clion的调试

以下调试 基于 jdk9 

呵呵 看到了 类似的代码, 那么 我们这里 来看下 0x7bf7ae340 是什么吧? 

java.lang.Class 
0x00000007bf7ae340 - klass: 'java/lang/Class'
 - ---- fields (total size 15 words):
 - private volatile transient strict 'cachedConstructor' 'Ljava/lang/reflect/Constructor;' @12  NULL (0 0)
 - private volatile transient strict 'newInstanceCallerCache' 'Ljava/lang/Class;' @16  NULL (0 f7ef5c79)
 - private transient 'name' 'Ljava/lang/String;' @20  "com.hx.test05.Test22VisibleToStop"0x00000007bf7ae3c8 (f7ef5c79 f7f2770f)
 - private transient 'module' 'Ljava/lang/Module;' @24  a 'java/lang/Module'0x00000007bf93b878 (f7f2770f f7f24ba8)
 - private final 'classLoader' 'Ljava/lang/ClassLoader;' @28  a 'jdk/internal/loader/ClassLoaders$AppClassLoader'0x00000007bf925d40 (f7f24ba8 f7ef52cc)
 - private transient 'packageName' 'Ljava/lang/String;' @32  "com.hx.test05"0x00000007bf7a9660 (f7ef52cc 0)
 - private final strict 'componentType' 'Ljava/lang/Class;' @36  NULL (0 f7ef5c9a)
 - private volatile transient strict 'reflectionData' 'Ljava/lang/ref/SoftReference;' @40  a 'java/lang/ref/SoftReference'0x00000007bf7ae4d0 (f7ef5c9a 0)
 - private volatile transient 'genericInfo' 'Lsun/reflect/generics/repository/ClassRepository;' @44  NULL (0 0)
 - private volatile transient strict 'enumConstants' '[Ljava/lang/Object;' @48  NULL (0 0)
 - private volatile transient strict 'enumConstantDirectory' 'Ljava/util/Map;' @52  NULL (0 0)
 - private volatile transient 'annotationData' 'Ljava/lang/Class$AnnotationData;' @56  NULL (0 0)
 - private volatile transient 'annotationType' 'Lsun/reflect/annotation/AnnotationType;' @60  NULL (0 0)
 - transient 'classValueMap' 'Ljava/lang/ClassValue$ClassValueMap;' @64  NULL (0 f7ef5ba3)
 - private volatile transient 'classRedefinedCount' 'I' @96  0
 - signature: Lcom/hx/test05/Test22VisibleToStop;
 - fake entry for mirror: 'com/hx/test05/Test22VisibleToStop'
 - fake entry for array: NULL
 - fake entry for oop_size: 15
 - fake entry for static_oop_field_count: 1
 - private static 'stop' 'Z' @116  true
 - private static volatile 'v2stop' 'Z' @117  true
 - private static strict 'map2stop' 'Ljava/util/HashMap;' @112  a 'java/util/HashMap'0x00000007bf7aee58 (f7ef5dcb 101)

呵呵 结合这一系列的 运行时的数据, 这可能就是 R大 所说的 循环不变量外提 的优化吧 

引用一下 R大 的原文 

楼上试试用JDK8(jdk1.8.0 build 132)的Client VM在同一环境下跑这个测试再看看如何?
在打开-Xcomp之后就能看到不同的效果 ^_^

这是因为JDK8的HotSpot VM的Client Compiler(C1)实现了循环不变量外提(loop invariant code motion)优化,所以在正常编译该例子的run()方法时能把stop的检查提到循环外面,这样就跟C2的状况一样了。

不打开-Xcomp看不到效果是因为这样跑该例子会让run()方法触发OSR编译而不是正常编译,正好干扰到C1实现的LICM优化了,于是stop的检查就还在循环里,于是还是能让循环结束。

PrintAssembly 的输出结果

当添加了 PrintAssembly 的相关选项之后, 复现不了 Thread-2 进入死循环的效果了 

这里贴一下 PrintAssembly 的输出结果 

Java HotSpot(TM) 64-Bit Server VM warning: PrintAssembly is enabled; turning on DebugNonSafepoints to gain additional output
CompilerOracle: dontinline *Test22VisibleToStop$3.run
CompilerOracle: compileonly *Test22VisibleToStop$3.run
Connected to the target VM, address: '127.0.0.1:58727', transport: 'socket'
map loop finish:2495652
map main stop
volatile loop finish:18327820
volatile main stop
Loaded disassembler from /Library/Java/JavaVirtualMachines/jdk1.8.0_211.jdk/Contents/Home/jre/lib/hsdis-amd64.dylib
Decoding compiled method 0x0000000112e20850:
Code:
[Disassembling for mach='i386:x86-64']
[Entry Point]
[Constants]
  # method 0x00000001265314c8 'run' '()V' in 'com/hx/test05/Test22VisibleToStop$3'
  #           [sp+0x60]  (sp of caller)
  0x0000000112e20a20: mov    0x8(%rsi),%r10d
  0x0000000112e20a24: shl    $0x3,%r10
  0x0000000112e20a28: cmp    %rax,%r10
  0x0000000112e20a2b: jne    0x0000000112d64e60  ;   runtime_call
  0x0000000112e20a31: data32 data32 nopw 0x0(%rax,%rax,1)
  0x0000000112e20a3c: data32 data32 xchg %ax,%ax
[Verified Entry Point]
  0x0000000112e20a40: mov    %eax,-0x14000(%rsp)
  0x0000000112e20a47: push   %rbp
  0x0000000112e20a48: sub    $0x50,%rsp
  0x0000000112e20a4c: mov    %rsi,0x28(%rsp)
  0x0000000112e20a51: movabs $0x1265316d0,%rdi  ;   metadata(method data for method 0x00000001265314c8 'run' '()V' in 'com/hx/test05/Test22VisibleToStop$3')
  0x0000000112e20a5b: mov    0xdc(%rdi),%ebx
  0x0000000112e20a61: add    $0x8,%ebx
  0x0000000112e20a64: mov    %ebx,0xdc(%rdi)
  0x0000000112e20a6a: movabs $0x1265314c8,%rdi  ;   metadata(method 0x00000001265314c8 'run' '()V' in 'com/hx/test05/Test22VisibleToStop$3')
  0x0000000112e20a74: and    $0x0,%ebx
  0x0000000112e20a77: cmp    $0x0,%ebx
  0x0000000112e20a7a: je     0x0000000112e20de8  ;*iconst_0
                                                ; - com.hx.test05.Test22VisibleToStop$3::run@0 (line 74)

  0x0000000112e20a80: mov    $0x0,%edi
  0x0000000112e20a85: jmpq   0x0000000112e20ade  ;*invokestatic access$200
                                                ; - com.hx.test05.Test22VisibleToStop$3::run@2 (line 75)

  0x0000000112e20a8a: nopw   0x0(%rax,%rax,1)
  0x0000000112e20a90: mov    0x20(%rsp),%edi
  0x0000000112e20a94: inc    %edi
  0x0000000112e20a96: movabs $0x1265316d0,%rdx  ;   metadata(method data for method 0x00000001265314c8 'run' '()V' in 'com/hx/test05/Test22VisibleToStop$3')
  0x0000000112e20aa0: mov    0xe0(%rdx),%esi
  0x0000000112e20aa6: add    $0x8,%esi
  0x0000000112e20aa9: mov    %esi,0xe0(%rdx)
  0x0000000112e20aaf: movabs $0x1265314c8,%rdx  ;   metadata(method 0x00000001265314c8 'run' '()V' in 'com/hx/test05/Test22VisibleToStop$3')
  0x0000000112e20ab9: and    $0xfff8,%esi
  0x0000000112e20abf: cmp    $0x0,%esi
  0x0000000112e20ac2: je     0x0000000112e20dff  ; OopMap[40]=Oop off=168
                                                ;*goto
                                                ; - com.hx.test05.Test22VisibleToStop$3::run@11 (line 76)

  0x0000000112e20ac8: test   %eax,-0x30799ce(%rip)        # 0x000000010fda7100
                                                ;   poll
  0x0000000112e20ace: movabs $0x1265316d0,%rdx  ;   metadata(method data for method 0x00000001265314c8 'run' '()V' in 'com/hx/test05/Test22VisibleToStop$3')
  0x0000000112e20ad8: incl   0x138(%rdx)        ;*goto
                                                ; - com.hx.test05.Test22VisibleToStop$3::run@11 (line 76)

  0x0000000112e20ade: mov    %edi,0x20(%rsp)
  0x0000000112e20ae2: movabs $0x1265316d0,%rbx  ;   metadata(method data for method 0x00000001265314c8 'run' '()V' in 'com/hx/test05/Test22VisibleToStop$3')
  0x0000000112e20aec: addq   $0x1,0x108(%rbx)
  0x0000000112e20af4: nop
  0x0000000112e20af5: nop
  0x0000000112e20af6: nop
  0x0000000112e20af7: callq  0x0000000112d65520  ; OopMap[40]=Oop off=220
                                                ;*invokestatic access$200
                                                ; - com.hx.test05.Test22VisibleToStop$3::run@2 (line 75)
                                                ;   static_call
  0x0000000112e20afc: cmp    $0x0,%eax
  0x0000000112e20aff: movabs $0x1265316d0,%rdx  ;   metadata(method data for method 0x00000001265314c8 'run' '()V' in 'com/hx/test05/Test22VisibleToStop$3')
  0x0000000112e20b09: movabs $0x118,%rsi
  0x0000000112e20b13: jne    0x0000000112e20b23
  0x0000000112e20b19: movabs $0x128,%rsi
  0x0000000112e20b23: mov    (%rdx,%rsi,1),%rdi
  0x0000000112e20b27: lea    0x1(%rdi),%rdi
  0x0000000112e20b2b: mov    %rdi,(%rdx,%rsi,1)
  0x0000000112e20b2f: je     0x0000000112e20a90  ;*ifne
                                                ; - com.hx.test05.Test22VisibleToStop$3::run@5 (line 75)

  0x0000000112e20b35: movabs $0x795580c78,%rdx  ;   oop(a 'java/lang/Class' = 'java/lang/System')
  0x0000000112e20b3f: mov    0x6c(%rdx),%ebx
  0x0000000112e20b42: shl    $0x3,%rbx          ;*getstatic out
                                                ; - com.hx.test05.Test22VisibleToStop$3::run@14 (line 78)

  0x0000000112e20b46: xchg   %ax,%ax
  0x0000000112e20b48: jmpq   0x0000000112e20e25  ;   no_reloc
  0x0000000112e20b4d: add    %al,(%rax)
  0x0000000112e20b4f: add    %al,(%rax)
  0x0000000112e20b51: add    %cl,-0x75(%rcx)
  0x0000000112e20b54: rex.RXB (bad)
  0x0000000112e20b56: lea    0x18(%rax),%rdi
  0x0000000112e20b5a: cmp    0x70(%r15),%rdi
  0x0000000112e20b5e: ja     0x0000000112e20e2f
  0x0000000112e20b64: mov    %rdi,0x60(%r15)
  0x0000000112e20b68: mov    0xa8(%rdx),%rcx
  0x0000000112e20b6f: mov    %rcx,(%rax)
  0x0000000112e20b72: mov    %rdx,%rcx
  0x0000000112e20b75: shr    $0x3,%rcx
  0x0000000112e20b79: mov    %ecx,0x8(%rax)
  0x0000000112e20b7c: xor    %rcx,%rcx
  0x0000000112e20b7f: mov    %ecx,0xc(%rax)
  0x0000000112e20b82: xor    %rcx,%rcx
  0x0000000112e20b85: mov    %rcx,0x10(%rax)    ;*new  ; - com.hx.test05.Test22VisibleToStop$3::run@17 (line 78)

  0x0000000112e20b89: mov    %rax,%rsi
  0x0000000112e20b8c: movabs $0x1265316d0,%rdi  ;   metadata(method data for method 0x00000001265314c8 'run' '()V' in 'com/hx/test05/Test22VisibleToStop$3')
  0x0000000112e20b96: addq   $0x1,0x150(%rdi)
  0x0000000112e20b9e: mov    %rax,%rsi          ;*invokespecial <init>
                                                ; - com.hx.test05.Test22VisibleToStop$3::run@21 (line 78)

  0x0000000112e20ba1: mov    %rbx,0x38(%rsp)
  0x0000000112e20ba6: mov    %rax,0x30(%rsp)
  0x0000000112e20bab: nop
  0x0000000112e20bac: nop
  0x0000000112e20bad: nop
  0x0000000112e20bae: nop
  0x0000000112e20baf: callq  0x0000000112d650a0  ; OopMap[48]=Oop [40]=Oop [56]=Oop off=404
                                                ;*invokespecial <init>
                                                ; - com.hx.test05.Test22VisibleToStop$3::run@21 (line 78)
                                                ;   optimized virtual_call
  0x0000000112e20bb4: mov    0x30(%rsp),%rax
  0x0000000112e20bb9: movabs $0x1265316d0,%rdx  ;   metadata(method data for method 0x00000001265314c8 'run' '()V' in 'com/hx/test05/Test22VisibleToStop$3')
  0x0000000112e20bc3: mov    0x8(%rax),%eax
  0x0000000112e20bc6: shl    $0x3,%rax
  0x0000000112e20bca: cmp    0x168(%rdx),%rax
  0x0000000112e20bd1: jne    0x0000000112e20be0
  0x0000000112e20bd3: addq   $0x1,0x170(%rdx)
  0x0000000112e20bdb: jmpq   0x0000000112e20c46
  0x0000000112e20be0: cmp    0x178(%rdx),%rax
  0x0000000112e20be7: jne    0x0000000112e20bf6
  0x0000000112e20be9: addq   $0x1,0x180(%rdx)
  0x0000000112e20bf1: jmpq   0x0000000112e20c46
  0x0000000112e20bf6: cmpq   $0x0,0x168(%rdx)
  0x0000000112e20c01: jne    0x0000000112e20c1a
  0x0000000112e20c03: mov    %rax,0x168(%rdx)
  0x0000000112e20c0a: movq   $0x1,0x170(%rdx)
  0x0000000112e20c15: jmpq   0x0000000112e20c46
  0x0000000112e20c1a: cmpq   $0x0,0x178(%rdx)
  0x0000000112e20c25: jne    0x0000000112e20c3e
  0x0000000112e20c27: mov    %rax,0x178(%rdx)
  0x0000000112e20c2e: movq   $0x1,0x180(%rdx)
  0x0000000112e20c39: jmpq   0x0000000112e20c46
  0x0000000112e20c3e: addq   $0x1,0x160(%rdx)
  0x0000000112e20c46: movabs $0x795c0cfb0,%rdx  ;   oop("basic type loop finish:")
  0x0000000112e20c50: mov    0x30(%rsp),%rsi    ;*invokevirtual append
                                                ; - com.hx.test05.Test22VisibleToStop$3::run@26 (line 78)

  0x0000000112e20c55: nop
  0x0000000112e20c56: nop
  0x0000000112e20c57: callq  0x0000000112d650a0  ; OopMap[40]=Oop [56]=Oop off=572
                                                ;*invokevirtual append
                                                ; - com.hx.test05.Test22VisibleToStop$3::run@26 (line 78)
                                                ;   optimized virtual_call
  0x0000000112e20c5c: cmp    (%rax),%rax        ; implicit exception: dispatches to 0x0000000112e20e3c
  0x0000000112e20c5f: mov    %rax,%rdx
  0x0000000112e20c62: movabs $0x1265316d0,%rsi  ;   metadata(method data for method 0x00000001265314c8 'run' '()V' in 'com/hx/test05/Test22VisibleToStop$3')
  0x0000000112e20c6c: mov    0x8(%rdx),%edx
  0x0000000112e20c6f: shl    $0x3,%rdx
  0x0000000112e20c73: cmp    0x198(%rsi),%rdx
  0x0000000112e20c7a: jne    0x0000000112e20c89
  0x0000000112e20c7c: addq   $0x1,0x1a0(%rsi)
  0x0000000112e20c84: jmpq   0x0000000112e20cef
  0x0000000112e20c89: cmp    0x1a8(%rsi),%rdx
  0x0000000112e20c90: jne    0x0000000112e20c9f
  0x0000000112e20c92: addq   $0x1,0x1b0(%rsi)
  0x0000000112e20c9a: jmpq   0x0000000112e20cef
  0x0000000112e20c9f: cmpq   $0x0,0x198(%rsi)
  0x0000000112e20caa: jne    0x0000000112e20cc3
  0x0000000112e20cac: mov    %rdx,0x198(%rsi)
  0x0000000112e20cb3: movq   $0x1,0x1a0(%rsi)
  0x0000000112e20cbe: jmpq   0x0000000112e20cef
  0x0000000112e20cc3: cmpq   $0x0,0x1a8(%rsi)
  0x0000000112e20cce: jne    0x0000000112e20ce7
  0x0000000112e20cd0: mov    %rdx,0x1a8(%rsi)
  0x0000000112e20cd7: movq   $0x1,0x1b0(%rsi)
  0x0000000112e20ce2: jmpq   0x0000000112e20cef
  0x0000000112e20ce7: addq   $0x1,0x190(%rsi)
  0x0000000112e20cef: mov    0x20(%rsp),%edx
  0x0000000112e20cf3: mov    %rax,%rsi          ;*invokevirtual append
                                                ; - com.hx.test05.Test22VisibleToStop$3::run@30 (line 78)

  0x0000000112e20cf6: nop
  0x0000000112e20cf7: callq  0x0000000112d650a0  ; OopMap[40]=Oop [56]=Oop off=732
                                                ;*invokevirtual append
                                                ; - com.hx.test05.Test22VisibleToStop$3::run@30 (line 78)
                                                ;   optimized virtual_call
  0x0000000112e20cfc: cmp    (%rax),%rax        ; implicit exception: dispatches to 0x0000000112e20e41
  0x0000000112e20cff: mov    %rax,%rsi
  0x0000000112e20d02: movabs $0x1265316d0,%rdi  ;   metadata(method data for method 0x00000001265314c8 'run' '()V' in 'com/hx/test05/Test22VisibleToStop$3')
  0x0000000112e20d0c: mov    0x8(%rsi),%esi
  0x0000000112e20d0f: shl    $0x3,%rsi
  0x0000000112e20d13: cmp    0x1c8(%rdi),%rsi
  0x0000000112e20d1a: jne    0x0000000112e20d29
  0x0000000112e20d1c: addq   $0x1,0x1d0(%rdi)
  0x0000000112e20d24: jmpq   0x0000000112e20d8f
  0x0000000112e20d29: cmp    0x1d8(%rdi),%rsi
  0x0000000112e20d30: jne    0x0000000112e20d3f
  0x0000000112e20d32: addq   $0x1,0x1e0(%rdi)
  0x0000000112e20d3a: jmpq   0x0000000112e20d8f
  0x0000000112e20d3f: cmpq   $0x0,0x1c8(%rdi)
  0x0000000112e20d4a: jne    0x0000000112e20d63
  0x0000000112e20d4c: mov    %rsi,0x1c8(%rdi)
  0x0000000112e20d53: movq   $0x1,0x1d0(%rdi)
  0x0000000112e20d5e: jmpq   0x0000000112e20d8f
  0x0000000112e20d63: cmpq   $0x0,0x1d8(%rdi)
  0x0000000112e20d6e: jne    0x0000000112e20d87
  0x0000000112e20d70: mov    %rsi,0x1d8(%rdi)
  0x0000000112e20d77: movq   $0x1,0x1e0(%rdi)
  0x0000000112e20d82: jmpq   0x0000000112e20d8f
  0x0000000112e20d87: addq   $0x1,0x1c0(%rdi)
  0x0000000112e20d8f: mov    %rax,%rsi          ;*invokevirtual toString
                                                ; - com.hx.test05.Test22VisibleToStop$3::run@33 (line 78)

  0x0000000112e20d92: nop
  0x0000000112e20d93: nop
  0x0000000112e20d94: nop
  0x0000000112e20d95: nop
  0x0000000112e20d96: nop
  0x0000000112e20d97: callq  0x0000000112d650a0  ; OopMap[40]=Oop [56]=Oop off=892
                                                ;*invokevirtual toString
                                                ; - com.hx.test05.Test22VisibleToStop$3::run@33 (line 78)
                                                ;   optimized virtual_call
  0x0000000112e20d9c: mov    0x38(%rsp),%rbx
  0x0000000112e20da1: cmp    (%rbx),%rax        ; implicit exception: dispatches to 0x0000000112e20e46
  0x0000000112e20da4: mov    %rbx,%rdx
  0x0000000112e20da7: movabs $0x1265316d0,%rsi  ;   metadata(method data for method 0x00000001265314c8 'run' '()V' in 'com/hx/test05/Test22VisibleToStop$3')
  0x0000000112e20db1: movabs $0x7c0027950,%r10  ;   metadata('java/io/PrintStream')
  0x0000000112e20dbb: mov    %r10,0x1f8(%rsi)
  0x0000000112e20dc2: addq   $0x1,0x200(%rsi)
  0x0000000112e20dca: mov    %rax,%rdx
  0x0000000112e20dcd: mov    %rbx,%rsi          ;*invokevirtual println
                                                ; - com.hx.test05.Test22VisibleToStop$3::run@36 (line 78)

  0x0000000112e20dd0: nop
  0x0000000112e20dd1: nop
  0x0000000112e20dd2: nop
  0x0000000112e20dd3: nop
  0x0000000112e20dd4: nop
  0x0000000112e20dd5: nop
  0x0000000112e20dd6: nop
  0x0000000112e20dd7: callq  0x0000000112d650a0  ; OopMap[40]=Oop off=956
                                                ;*invokevirtual println
                                                ; - com.hx.test05.Test22VisibleToStop$3::run@36 (line 78)
                                                ;   optimized virtual_call
  0x0000000112e20ddc: add    $0x50,%rsp
  0x0000000112e20de0: pop    %rbp
  0x0000000112e20de1: test   %eax,-0x3079ce7(%rip)        # 0x000000010fda7100
                                                ;   poll_return
  0x0000000112e20de7: retq
  0x0000000112e20de8: mov    %rdi,0x8(%rsp)
  0x0000000112e20ded: movq   $0xffffffffffffffff,(%rsp)
  0x0000000112e20df5: callq  0x0000000112e1f5a0  ; OopMaprsi=Oop [40]=Oop off=986
                                                ;*synchronization entry
                                                ; - com.hx.test05.Test22VisibleToStop$3::run@-1 (line 74)
                                                ;   runtime_call
  0x0000000112e20dfa: jmpq   0x0000000112e20a80
  0x0000000112e20dff: mov    %rdx,0x8(%rsp)
  0x0000000112e20e04: movq   $0xb,(%rsp)
  0x0000000112e20e0c: callq  0x0000000112e1f5a0  ; OopMap[40]=Oop off=1009
                                                ;*goto
                                                ; - com.hx.test05.Test22VisibleToStop$3::run@11 (line 76)
                                                ;   runtime_call
  0x0000000112e20e11: jmpq   0x0000000112e20ac8
  0x0000000112e20e16: movabs $0x0,%rdx          ;   metadata(NULL)
  0x0000000112e20e20: mov    $0xa050f00,%eax
  0x0000000112e20e25: callq  0x0000000112e1e460  ; OopMap[40]=Oop rbx=Oop off=1034
                                                ;*new  ; - com.hx.test05.Test22VisibleToStop$3::run@17 (line 78)
                                                ;   runtime_call
  0x0000000112e20e2a: jmpq   0x0000000112e20b48
  0x0000000112e20e2f: mov    %rdx,%rdx
  0x0000000112e20e32: callq  0x0000000112e1b560  ; OopMaprbx=Oop [40]=Oop off=1047
                                                ;*new  ; - com.hx.test05.Test22VisibleToStop$3::run@17 (line 78)
                                                ;   runtime_call
  0x0000000112e20e37: jmpq   0x0000000112e20b89
  0x0000000112e20e3c: callq  0x0000000112e1ae00  ; OopMap[40]=Oop [56]=Oop rax=Oop off=1057
                                                ;*invokevirtual append
                                                ; - com.hx.test05.Test22VisibleToStop$3::run@30 (line 78)
                                                ;   runtime_call
  0x0000000112e20e41: callq  0x0000000112e1ae00  ; OopMap[40]=Oop [56]=Oop rax=Oop off=1062
                                                ;*invokevirtual toString
                                                ; - com.hx.test05.Test22VisibleToStop$3::run@33 (line 78)
                                                ;   runtime_call
  0x0000000112e20e46: callq  0x0000000112e1ae00  ; OopMap[40]=Oop rax=Oop rbx=Oop off=1067
                                                ;*invokevirtual println
                                                ; - com.hx.test05.Test22VisibleToStop$3::run@36 (line 78)
                                                ;   runtime_call
  0x0000000112e20e4b: nop
  0x0000000112e20e4c: nop
  0x0000000112e20e4d: mov    0x2a8(%r15),%rax
  0x0000000112e20e54: movabs $0x0,%r10
  0x0000000112e20e5e: mov    %r10,0x2a8(%r15)
  0x0000000112e20e65: movabs $0x0,%r10
  0x0000000112e20e6f: mov    %r10,0x2b0(%r15)
  0x0000000112e20e76: add    $0x50,%rsp
  0x0000000112e20e7a: pop    %rbp
  0x0000000112e20e7b: jmpq   0x0000000112d8d960  ;   runtime_call
[Stub Code]
  0x0000000112e20e80: nop                       ;   no_reloc
  0x0000000112e20e81: nop
  0x0000000112e20e82: nop
  0x0000000112e20e83: nop
  0x0000000112e20e84: nop
  0x0000000112e20e85: movabs $0x0,%rbx          ;   static_stub
  0x0000000112e20e8f: jmpq   0x0000000112e20e8f  ;   runtime_call
  0x0000000112e20e94: nop
  0x0000000112e20e95: movabs $0x0,%rbx          ;   static_stub
  0x0000000112e20e9f: jmpq   0x0000000112e20e9f  ;   runtime_call
  0x0000000112e20ea4: nop
  0x0000000112e20ea5: movabs $0x0,%rbx          ;   static_stub
  0x0000000112e20eaf: jmpq   0x0000000112e20eaf  ;   runtime_call
  0x0000000112e20eb4: nop
  0x0000000112e20eb5: movabs $0x0,%rbx          ;   static_stub
  0x0000000112e20ebf: jmpq   0x0000000112e20ebf  ;   runtime_call
  0x0000000112e20ec4: nop
  0x0000000112e20ec5: movabs $0x0,%rbx          ;   static_stub
  0x0000000112e20ecf: jmpq   0x0000000112e20ecf  ;   runtime_call
  0x0000000112e20ed4: nop
  0x0000000112e20ed5: movabs $0x0,%rbx          ;   static_stub
  0x0000000112e20edf: jmpq   0x0000000112e20edf  ;   runtime_call
[Exception Handler]
  0x0000000112e20ee4: callq  0x0000000112e1cca0  ;   runtime_call
  0x0000000112e20ee9: mov    %rsp,-0x28(%rsp)
  0x0000000112e20eee: sub    $0x80,%rsp
  0x0000000112e20ef5: mov    %rax,0x78(%rsp)
  0x0000000112e20efa: mov    %rcx,0x70(%rsp)
  0x0000000112e20eff: mov    %rdx,0x68(%rsp)
  0x0000000112e20f04: mov    %rbx,0x60(%rsp)
  0x0000000112e20f09: mov    %rbp,0x50(%rsp)
  0x0000000112e20f0e: mov    %rsi,0x48(%rsp)
  0x0000000112e20f13: mov    %rdi,0x40(%rsp)
  0x0000000112e20f18: mov    %r8,0x38(%rsp)
  0x0000000112e20f1d: mov    %r9,0x30(%rsp)
  0x0000000112e20f22: mov    %r10,0x28(%rsp)
  0x0000000112e20f27: mov    %r11,0x20(%rsp)
  0x0000000112e20f2c: mov    %r12,0x18(%rsp)
  0x0000000112e20f31: mov    %r13,0x10(%rsp)
  0x0000000112e20f36: mov    %r14,0x8(%rsp)
  0x0000000112e20f3b: mov    %r15,(%rsp)
  0x0000000112e20f3f: movabs $0x1113de684,%rdi  ;   external_word
  0x0000000112e20f49: movabs $0x112e20ee9,%rsi  ;   internal_word
  0x0000000112e20f53: mov    %rsp,%rdx
  0x0000000112e20f56: and    $0xfffffffffffffff0,%rsp
  0x0000000112e20f5a: callq  0x00000001112071f6  ;   runtime_call
  0x0000000112e20f5f: hlt
[Deopt Handler Code]
  0x0000000112e20f60: movabs $0x112e20f60,%r10  ;   section_word
  0x0000000112e20f6a: push   %r10
  0x0000000112e20f6c: jmpq   0x0000000112d66500  ;   runtime_call
  0x0000000112e20f71: hlt
  0x0000000112e20f72: hlt
  0x0000000112e20f73: hlt
  0x0000000112e20f74: hlt
  0x0000000112e20f75: hlt
  0x0000000112e20f76: hlt
  0x0000000112e20f77: hlt

Decoding compiled method 0x0000000112e2cb50:
Code:
[Entry Point]
[Constants]
  # method 0x00000001265314c8 'run' '()V' in 'com/hx/test05/Test22VisibleToStop$3'
  #           [sp+0x30]  (sp of caller)
  0x0000000112e2cca0: mov    0x8(%rsi),%r10d
  0x0000000112e2cca4: shl    $0x3,%r10
  0x0000000112e2cca8: cmp    %r10,%rax
  0x0000000112e2ccab: jne    0x0000000112d64e60  ;   runtime_call
  0x0000000112e2ccb1: data32 xchg %ax,%ax
  0x0000000112e2ccb4: nopl   0x0(%rax,%rax,1)
  0x0000000112e2ccbc: data32 data32 xchg %ax,%ax
[Verified Entry Point]
  0x0000000112e2ccc0: mov    %eax,-0x14000(%rsp)
  0x0000000112e2ccc7: push   %rbp
  0x0000000112e2ccc8: sub    $0x20,%rsp         ;*synchronization entry
                                                ; - com.hx.test05.Test22VisibleToStop$3::run@-1 (line 74)

  0x0000000112e2cccc: mov    %rsi,(%rsp)
  0x0000000112e2ccd0: data32 xchg %ax,%ax
  0x0000000112e2ccd3: callq  0x0000000112d65520  ; OopMap[0]=Oop off=56
                                                ;*invokestatic access$200
                                                ; - com.hx.test05.Test22VisibleToStop$3::run@2 (line 75)
                                                ;   static_call
  0x0000000112e2ccd8: test   %eax,%eax
  0x0000000112e2ccda: jne    0x0000000112e2cd25  ;*ifne
                                                ; - com.hx.test05.Test22VisibleToStop$3::run@5 (line 75)

  0x0000000112e2ccdc: mov    $0x1,%r11d
  0x0000000112e2cce2: mov    %r11d,0x8(%rsp)
  0x0000000112e2cce7: jmp    0x0000000112e2ccfd
  0x0000000112e2cce9: nopl   0x0(%rax)
  0x0000000112e2ccf0: mov    0x8(%rsp),%r10d
  0x0000000112e2ccf5: inc    %r10d
  0x0000000112e2ccf8: mov    %r10d,0x8(%rsp)    ;*iinc
                                                ; - com.hx.test05.Test22VisibleToStop$3::run@8 (line 76)

  0x0000000112e2ccfd: xchg   %ax,%ax
  0x0000000112e2ccff: callq  0x0000000112d65520  ; OopMap[0]=Oop off=100
                                                ;*invokestatic access$200
                                                ; - com.hx.test05.Test22VisibleToStop$3::run@2 (line 75)
                                                ;   static_call
  0x0000000112e2cd04: test   %eax,%eax
  0x0000000112e2cd06: je     0x0000000112e2ccf0  ;*ifne
                                                ; - com.hx.test05.Test22VisibleToStop$3::run@5 (line 75)

  0x0000000112e2cd08: mov    $0x4,%esi
  0x0000000112e2cd0d: movabs $0x795580c78,%r10  ;   oop(a 'java/lang/Class' = 'java/lang/System')
  0x0000000112e2cd17: mov    0x6c(%r10),%ebp
  0x0000000112e2cd1b: callq  0x0000000112d646a0  ; OopMaprbp=NarrowOop [0]=Oop off=128
                                                ;*new  ; - com.hx.test05.Test22VisibleToStop$3::run@17 (line 78)
                                                ;   runtime_call
  0x0000000112e2cd20: callq  0x000000011128a904  ;*new
                                                ; - com.hx.test05.Test22VisibleToStop$3::run@17 (line 78)
                                                ;   runtime_call
  0x0000000112e2cd25: xor    %r10d,%r10d
  0x0000000112e2cd28: mov    %r10d,0x8(%rsp)
  0x0000000112e2cd2d: jmp    0x0000000112e2cd08
  0x0000000112e2cd2f: mov    %rax,%rsi
  0x0000000112e2cd32: jmp    0x0000000112e2cd37
  0x0000000112e2cd34: mov    %rax,%rsi          ;*invokestatic access$200
                                                ; - com.hx.test05.Test22VisibleToStop$3::run@2 (line 75)

  0x0000000112e2cd37: add    $0x20,%rsp
  0x0000000112e2cd3b: pop    %rbp
  0x0000000112e2cd3c: jmpq   0x0000000112e21820  ;   runtime_call
  0x0000000112e2cd41: hlt
  0x0000000112e2cd42: hlt
  0x0000000112e2cd43: hlt
  0x0000000112e2cd44: hlt
  0x0000000112e2cd45: hlt
  0x0000000112e2cd46: hlt
  0x0000000112e2cd47: hlt
  0x0000000112e2cd48: hlt
  0x0000000112e2cd49: hlt
  0x0000000112e2cd4a: hlt
  0x0000000112e2cd4b: hlt
  0x0000000112e2cd4c: hlt
  0x0000000112e2cd4d: hlt
  0x0000000112e2cd4e: hlt
  0x0000000112e2cd4f: hlt
  0x0000000112e2cd50: hlt
  0x0000000112e2cd51: hlt
  0x0000000112e2cd52: hlt
  0x0000000112e2cd53: hlt
  0x0000000112e2cd54: hlt
  0x0000000112e2cd55: hlt
  0x0000000112e2cd56: hlt
  0x0000000112e2cd57: hlt
  0x0000000112e2cd58: hlt
  0x0000000112e2cd59: hlt
  0x0000000112e2cd5a: hlt
  0x0000000112e2cd5b: hlt
  0x0000000112e2cd5c: hlt
  0x0000000112e2cd5d: hlt
  0x0000000112e2cd5e: hlt
  0x0000000112e2cd5f: hlt
[Stub Code]
  0x0000000112e2cd60: movabs $0x0,%rbx          ;   no_reloc
  0x0000000112e2cd6a: jmpq   0x0000000112e2cd6a  ;   runtime_call
  0x0000000112e2cd6f: movabs $0x0,%rbx          ;   static_stub
  0x0000000112e2cd79: jmpq   0x0000000112e2cd79  ;   runtime_call
[Exception Handler]
  0x0000000112e2cd7e: jmpq   0x0000000112d76da0  ;   runtime_call
[Deopt Handler Code]
  0x0000000112e2cd83: callq  0x0000000112e2cd88
  0x0000000112e2cd88: subq   $0x5,(%rsp)
  0x0000000112e2cd8d: jmpq   0x0000000112d66500  ;   runtime_call
  0x0000000112e2cd92: hlt
  0x0000000112e2cd93: hlt
  0x0000000112e2cd94: hlt
  0x0000000112e2cd95: hlt
  0x0000000112e2cd96: hlt
  0x0000000112e2cd97: hlt
Decoding compiled method 0x0000000112e2c7d0:
Code:
[Entry Point]
[Verified Entry Point]
[Constants]
  # method 0x00000001265314c8 'run' '()V' in 'com/hx/test05/Test22VisibleToStop$3'
  0x0000000112e2c920: callq  0x000000011128a904  ;   runtime_call
  0x0000000112e2c925: data32 data32 nopw 0x0(%rax,%rax,1)
  0x0000000112e2c930: mov    %eax,-0x14000(%rsp)
  0x0000000112e2c937: push   %rbp
  0x0000000112e2c938: sub    $0x20,%rsp
  0x0000000112e2c93c: mov    (%rsi),%ebx
  0x0000000112e2c93e: mov    0x8(%rsi),%rbp
  0x0000000112e2c942: mov    %rsi,%rdi
  0x0000000112e2c945: movabs $0x1112e9b52,%r10
  0x0000000112e2c94f: callq  *%r10
  0x0000000112e2c952: test   %rbp,%rbp
  0x0000000112e2c955: je     0x0000000112e2c9ad
  0x0000000112e2c957: mov    0x8(%rbp),%r10d
  0x0000000112e2c95b: cmp    $0xf800c461,%r10d  ;   metadata('com/hx/test05/Test22VisibleToStop$3')
  0x0000000112e2c962: jne    0x0000000112e2c9b1  ;*invokestatic access$200
                                                ; - com.hx.test05.Test22VisibleToStop$3::run@2 (line 75)

  0x0000000112e2c964: jmp    0x0000000112e2c97c
  0x0000000112e2c966: data32 nopw 0x0(%rax,%rax,1)
  0x0000000112e2c970: mov    0x8(%rsp),%ebx
  0x0000000112e2c974: inc    %ebx               ; OopMaprbp=Oop off=86
                                                ;*goto
                                                ; - com.hx.test05.Test22VisibleToStop$3::run@11 (line 76)

  0x0000000112e2c976: test   %eax,-0x308597c(%rip)        # 0x000000010fda7000
                                                ;   poll
  0x0000000112e2c97c: mov    %rbp,(%rsp)
  0x0000000112e2c980: mov    %ebx,0x8(%rsp)
  0x0000000112e2c984: data32 xchg %ax,%ax
  0x0000000112e2c987: callq  0x0000000112d65520  ; OopMaprbp=Oop [0]=Oop off=108
                                                ;*invokestatic access$200
                                                ; - com.hx.test05.Test22VisibleToStop$3::run@2 (line 75)
                                                ;   static_call
  0x0000000112e2c98c: test   %eax,%eax
  0x0000000112e2c98e: je     0x0000000112e2c970  ;*ifne
                                                ; - com.hx.test05.Test22VisibleToStop$3::run@5 (line 75)

  0x0000000112e2c990: mov    $0x4,%esi
  0x0000000112e2c995: movabs $0x795580c78,%r10  ;   oop(a 'java/lang/Class' = 'java/lang/System')
  0x0000000112e2c99f: mov    0x6c(%r10),%ebp
  0x0000000112e2c9a3: callq  0x0000000112d646a0  ; OopMaprbp=NarrowOop [0]=Oop off=136
                                                ;*new  ; - com.hx.test05.Test22VisibleToStop$3::run@17 (line 78)
                                                ;   runtime_call
  0x0000000112e2c9a8: callq  0x000000011128a904  ;*new
                                                ; - com.hx.test05.Test22VisibleToStop$3::run@17 (line 78)
                                                ;   runtime_call
  0x0000000112e2c9ad: xor    %ebp,%ebp
  0x0000000112e2c9af: jmp    0x0000000112e2c97c
  0x0000000112e2c9b1: mov    $0xffffff9d,%esi
  0x0000000112e2c9b6: mov    %ebx,(%rsp)
  0x0000000112e2c9b9: xchg   %ax,%ax
  0x0000000112e2c9bb: callq  0x0000000112d646a0  ; OopMaprbp=Oop off=160
                                                ;*invokestatic access$200
                                                ; - com.hx.test05.Test22VisibleToStop$3::run@2 (line 75)
                                                ;   runtime_call
  0x0000000112e2c9c0: callq  0x000000011128a904  ;   runtime_call
  0x0000000112e2c9c5: mov    %rax,%rsi
  0x0000000112e2c9c8: add    $0x20,%rsp
  0x0000000112e2c9cc: pop    %rbp
  0x0000000112e2c9cd: jmpq   0x0000000112e21820  ;*invokestatic access$200
                                                ; - com.hx.test05.Test22VisibleToStop$3::run@2 (line 75)
                                                ;   runtime_call
  0x0000000112e2c9d2: hlt
  0x0000000112e2c9d3: hlt
  0x0000000112e2c9d4: hlt
  0x0000000112e2c9d5: hlt
  0x0000000112e2c9d6: hlt
  0x0000000112e2c9d7: hlt
  0x0000000112e2c9d8: hlt
  0x0000000112e2c9d9: hlt
  0x0000000112e2c9da: hlt
  0x0000000112e2c9db: hlt
  0x0000000112e2c9dc: hlt
  0x0000000112e2c9dd: hlt
  0x0000000112e2c9de: hlt
  0x0000000112e2c9df: hlt
[Stub Code]
  0x0000000112e2c9e0: movabs $0x0,%rbx          ;   no_reloc
  0x0000000112e2c9ea: jmpq   0x0000000112e2c9ea  ;   runtime_call
[Exception Handler]
  0x0000000112e2c9ef: jmpq   0x0000000112d76da0  ;   runtime_call
[Deopt Handler Code]
  0x0000000112e2c9f4: callq  0x0000000112e2c9f9
  0x0000000112e2c9f9: subq   $0x5,(%rsp)
  0x0000000112e2c9fe: jmpq   0x0000000112d66500  ;   runtime_call
  0x0000000112e2ca03: hlt
  0x0000000112e2ca04: hlt
  0x0000000112e2ca05: hlt
  0x0000000112e2ca06: hlt
  0x0000000112e2ca07: hlt
basic type loop finish:17687011
basic type main stop
basic type with sync loop finish:0
basic type with sync main stop
Disconnected from the target VM, address: '127.0.0.1:58727', transport: 'socket'

Process finished with exit code 0

可以看出 编译了 三个版本, 其中 第二个版本 逻辑更加容易 理解一些 

如果有兴趣的话 可以看一下第一个版本, 呵呵 反正我是没看, 有点麻烦 

根据 bx 查看一下运行时方法的信息

呵呵 发现了这个的话, 我觉得 以这个例子 理解一下 Method 的 _from_interpreted_entry, _from_compiled_entry, _i2i_entry, code 这几个东西了 

呵呵 另外一件事情, 就是 看到了 Method 里面的 MethodData 和 MethodCounters 了, 之前调试的时候 大部分的时候 看到的都是 NULL 

相关疑问?

1. -Xint, -Xcomp 都能够正常结束, -Xmixed 不行 ? 

可能可以从 R大 上面的这段解释 中找出原因吧, 不过 终究还是 道行太浅, 没得依据 

2. 在 Thread-2 里面打上断点, 放掉 就能够退出了 

呵呵 可能是 hit 到断点的时候, 回退了运行时 执行的代码吧, 之类的, 没得依据 

添加于2020.03.01 - 找到的一个合理的解释

呵呵 最近的时候, 在 perfma 社区看到了一篇文章 

一道面试题引发的对Java内存模型的一点疑问,第二部。这篇文章可以关联到文章 一道面试题引发的对Java内存模型的一点疑问?这篇文章又可以关联到知乎的一篇文章 java中volatile关键字的疑惑?

这里面的解释, 虽然我目前 还有一些 没有明白的地方, 但是根据我的调试, 最终运行时的这些东西 和 文章中的论证的结论是一致的 

呵呵 多久再细看一下 hb, 在研究研究, 目前还了解的不够吧 

测试用例

先看看测试用例, 和原文的用例差不多的 

/**
 * Test13InfiniteLoop
 *
 * @author Jerry.X.He <970655147@qq.com>
 * @version 1.0
 * @date 2021-02-22 11:14
 */
public class Test13InfiniteLoop 

    static int num = 11; // 0/1/11

    // Test13InfiniteLoop, 死循环
    // refer : https://club.perfma.com/question/2079981
    // refer : https://club.perfma.com/question/267086
    // refer : https://www.zhihu.com/question/263528143/answer/270308453
    public static void main(String[] args) 

        new Thread(() -> 
            System.out.println(" child -> " + num);
            try 
                Thread.sleep(1000);
             catch (Exception e) 
                e.printStackTrace();
            

            num++;
            System.out.println(" child -> " + num);
        ).start();

        System.out.println(" main -> " + num);
        int counter = 0;
        while (num == 11) 
            counter++;
//            System.out.println(" main -> " + num);
        
        System.out.println(" main -> " + num);
        System.out.println(" main -> " + counter);
    

我们这会看 num 初始化为 0, 1, 11 的三种场景 

之所以这里处理 num 这三种情况, 是因为 num 为 0 的时候, 我们判断不出 前面的这一个 test 指令是否是对应于 main 里面的 "while (num == 11)" 的判断

num 为 0 的情况

main 线程的运行时的代码的信息如下, 可以看出 "testl  %r11d, %r11d"  大致是 "while (num == 0)" 的判断, 下面的 0x10cb718c5 以及紧接着的三条指令为 循环里面的业务代码 

(lldb) dis -s 0x10cb718a0 -c 100
    0x10cb718a0: movl   %esi, %edi
    0x10cb718a2: movabsq $0x1045ec000, %r10        ; imm = 0x1045EC000
    0x10cb718ac: callq  *%r10
    0x10cb718af: movabsq $0x747bb8860, %r10        ; imm = 0x747BB8860
    0x10cb718b9: movl   0x70(%r10), %r11d
    0x10cb718bd: testl  %r11d, %r11d
    0x10cb718c0: jne    0x10cb718d0
    0x10cb718c2: incl   %r13d
->  0x10cb718c5: incl   %r13d
    0x10cb718c8: testl  %eax, -0xc7008ce(%rip)
    0x10cb718ce: jmp    0x10cb718c5
    0x10cb718d0: movl   %r11d, %r10d
    0x10cb718d3: negl   %r10d
    0x10cb718d6: cmpl   $0x80000000, %r11d        ; imm = 0x80000000
    0x10cb718dd: jne    0x10cb71ffb
    0x10cb718e3: movl   $0x14, %ebp
    0x10cb718e8: movl   $0x1, %r8d
    0x10cb718ee: movl   $0x14, %ecx
    0x10cb718f3: jmp    0x10cb7191c
    0x10cb718f5: nop
    // 省略一部分记录信息

num 为 1 的情况

main 线程的运行时的代码的信息如下, 可以看出 "cmpl   $0x1, %r10d"  大致是 "while (num == 1)" 的判断, 下面的 0x10dafe302 以及紧接着的三条指令为 循环里面的业务代码 

(lldb) dis -s 0x10dafe2f0 -c 100
    0x10dafe2f0: cmpb   %cl, 0x747bb(%rax)
    0x10dafe2f6: addb   %al, (%rax)
    0x10dafe2f8: movl   0x70(%r10), %r10d
    0x10dafe2fc: cmpl   $0x1, %r10d
    0x10dafe300: jne    0x10dafe30c
    0x10dafe302: incl   %ebp
->  0x10dafe304: testl  %eax, -0xd78d30a(%rip)
    0x10dafe30a: jmp    0x10dafe302
    0x10dafe30c: movl   $0xffffff86, %esi         ; imm = 0xFFFFFF86 
    0x10dafe311: nop    
    // 省略一部分记录信息

num 为 11 的情况

main 线程的运行时的代码的信息如下, 可以看出 "cmpl   $0xb, %r11d"  大致是 "while (num == 11)" 的判断, 下面的 0x10c382546 以及紧接着的三条指令为 循环里面的业务代码 

(lldb) dis -s 0x10c382531 -c 100
    0x10c382531: orb    %cl, 0x747bb(%rcx)
    0x10c382537: addb   %al, (%rax)
    0x10c382539: movl   0x70(%r10), %r11d
    0x10c38253d: cmpl   $0xb, %r11d
    0x10c382541: jne    0x10c382551
    0x10c382543: incl   %r13d
->  0x10c382546: incl   %r13d
    0x10c382549: testl  %eax, -0xc11154f(%rip)
    0x10c38254f: jmp    0x10c382546
    0x10c382551: movl   %r11d, %r10d
    0x10c382554: negl   %r10d
    0x10c382557: cmpl   $0x80000000, %r11d        ; imm = 0x80000000
    0x10c38255e: jne    0x10c382c7b
    0x10c382564: movl   $0x14, %ebp
    0x10c382569: movl   $0x1, %r8d
    0x10c38256f: movl   $0x14, %ecx
    0x10c382574: jmp    0x10c38259c
    0x10c382576: nop
	// 省略一部分记录信息

记录就差不多到这里了, 结果是和 这篇文章的记录是吻合的 

代码确实是被替换成了, 类似于 如下的代码片 

if (num == 11) 
	while(true) 
		counter++;
	

完 

参考

[讨论] 内存可见性问题

一道面试题引发的对Java内存模型的一点疑问,第二部。

一道面试题引发的对Java内存模型的一点疑问?

java中volatile关键字的疑惑?

以上是关于59 多线程环境普通变量作为标记循环不结束的主要内容,如果未能解决你的问题,请参考以下文章

59 多线程环境普通变量作为标记循环不结束

delphi 多线程问题

Java多线程

Java多线程循环打印ABC的5种实现方法

JAVA多线程模式-Two Phase Termination

Java多线程:用三个线程控制循环输出10次ABC