首先我们来看一段如下代码
public class VisibilityDemo {
public static class VisibilityThread extends Thread {
private boolean stop;
@Override
public void run() {
int i = 0;
while (!stop) {
i++;
}
System.out.println("finish loop,i=" \+ i);
}
public void stopLt() {
stop = true;
}
public boolean getStop() {
return stop;
}
}
public static void main(String\[\] args) throws InterruptedException {
VisibilityThread v = new VisibilityThread();
v.start();
Thread.sleep(1000);
v.stopLt();
Thread.sleep(2000);
System.out.println("finish main");
System.out.println(v.getStop());
}
}
按照正常的逻辑 循环肯定是能结束的,但实际上我们运行之后发现,循环是无法停止的
我们反汇编程序看到如下的情况, 如何查看反汇编代码在博客内有相应文章
0x0000000002e2a120: mov dword ptr \[rsp+0ffffffffffffa000h\],eax
0x0000000002e2a127: push rbp
0x0000000002e2a128: sub rsp,20h ;*synchronization entry
; \- package.VisibilityDemo$VisibilityThread::run@-1 (line 13)
0x0000000002e2a12c: mov r10,rdx
// 获取stop的值放入 ebp寄存器
0x0000000002e2a12f: movzx ebp,byte ptr \[rdx+178h\] ;*getfield stop
; \- package.VisibilityDemo$VisibilityThread::run@3 (line 14)
// 测试 stop的值是否为true
0x0000000002e2a136: test ebp,ebp
// 如果测试通过 跳转至 2e2a14b 进行打印输出
0x0000000002e2a138: jne 2e2a14bh ;*ifne
; \- package.VisibilityDemo$VisibilityThread::run@6 (line 14)
// 不满足条件 进入循环体
0x0000000002e2a13a: mov r11d,1h ; OopMap{r10=Oop off=64}
;*goto
; \- package.VisibilityDemo$VisibilityThread::run@12 (line 15)
// 这个test 是jvm的检查点
0x0000000002e2a140: test dword ptr \[960000h\],eax ;*goto
; \- package.VisibilityDemo$VisibilityThread::run@12 (line 15)
; {poll}
// i++
0x0000000002e2a146: inc r11d ;*iinc
; \- package.VisibilityDemo$VisibilityThread::run@9 (line 15)
// 无条件跳转至2e2a140
0x0000000002e2a149: jmp 2e2a140h
0x0000000002e2a14b: mov edx,0ffffff65h
0x0000000002e2a150: mov qword ptr \[rsp\],r10
0x0000000002e2a154: nop
0x0000000002e2a157: call 2d557a0h ; OopMap{\[0\]=Oop off=92}
;*ifne
; \- package.VisibilityDemo$VisibilityThread::run@6 (line 14)
; {runtime_call}
分析以上汇编代码,我们得到一个结论
这段Java代码被jvm优化成了类似于如下代码的结构
if(!stop){
while(true){
i++;
}
}
评论区