gpt4 book ai didi

java - 在Java中,构造函数中的final字段赋值涉及到哪些操作?

转载 作者:行者123 更新时间:2023-12-01 19:36:13 25 4
gpt4 key购买 nike

如果 Simple 类字段 afinal 关键字修改,则以下代码会得到不同的执行结果。

如果a是final字段,则该程序将正常退出;如果是普通字段,则该程序将一直运行。

这种情况只发生在C2编译器中。

我认为这种情况与多线程环境中flag字段的可见性有关。但是,我尝试通过hsdis观察汇编代码,发现有和没有final关键字的区别。

我发现没有什么区别。

实际上,我知道存储“final”字段不会在 x86 平台上发出任何汇编指令。但为什么会出现这样的情况呢?是否有一些我不知道的特定操作?

感谢您的阅读。

class MultiProcessorTask {

private boolean flag= true;

public void runMethod() {
while (flag) {
new Simple(1);
}
}

public void stopMethod() {
System.out.println("change 'flag' field ...");
flag= false;
}
}


class ThreadA extends Thread {

private MultiProcessorTask task;

ThreadA(MultiProcessorTask task) {this.task = task;}

@Override
public void run() {
task.runMethod();
}
}

class Simple {
private int a; // modify "a" as "final"

Simple(int a) {this.a = a;}
}

public class TestRun {
public static void main(String[] args) {
MultiProcessorTask task = new MultiProcessorTask();
ThreadA a = new ThreadA(task);
a.start();
task.stopMethod();
System.out.println("it's over");
}
}

反汇编代码输出:

  • final 情况下的 runMethod:

the final case

  • 非最终情况下的runMethod:

the non-final case

最佳答案

您反汇编了错误的编译。我的意思是,两个屏幕截图上都有一个独立编译的 runMethod,但是,它在现实中从未执行过。相反,执行从解释器跳转到 OSR stub 。您需要查找标有 % 符号(表示堆栈上替换)的编译。

Compiled method (c2)     646  662 %           MultiProcessorTask::runMethod @ 0 (20 bytes)
^
OSR

这是非最终和最终情况之间编译代码的差异。我只留下了相关部分:

非最终版

  0x000000000309ae31: test   %eax,-0x5aae37(%rip)   ; safepoint poll
0x000000000309ae37: jmp 0x000000000309ae31 ; loop

最终

  0x0000000002c3a3a0: test   %eax,-0x265a3a6(%rip)  ; safepoint poll
0x0000000002c3a3a6: movzbl 0xc(%rbx),%r11d ; load 'flag' field
0x0000000002c3a3ab: test %r11d,%r11d
0x0000000002c3a3ae: jne 0x0000000002c3a3a0 ; loop if flag == true

事实上,第一种情况被编译为无限循环,而第二种情况保留了字段检查。

您会看到,在这两种情况下,根本没有 Simple 实例分配,也没有字段分配。因此,这不是用于编译 final 字段赋值的指令的问题,而是编译器级别的障碍,它阻止将 flag 字段缓存到循环之外。

但是由于完全消除了分配,因此 final 字段分配所隐含的障碍也可以消失。在这里我们看到错失了优化机会。事实上,这种错过的优化在较新的 JVM 版本中已得到修复。如果您在 JDK 11 上运行相同的示例,则无论 final 修饰符如何,这两种情况都会出现无限循环。

关于java - 在Java中,构造函数中的final字段赋值涉及到哪些操作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57427531/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com