当前位置: 首页 > 知识库问答 >
问题:

编译器优化是否改变了以下代码中语句的执行?[重复]

宰父淳
2023-03-14

在最近的一个相关问题中,我发现以下代码

public static void main(String[] args) {
/*1*/        int x;
/*2*/        boolean found = false;
/*3*/        if (!found)
/*4*/            x = -1;

/*5*/        System.out.println(x);
    }

存在编译器错误,x不是init。(初始化)。令我惊讶的是,编译器无法推理init。尤其是因为这段代码似乎不需要任何运行时推理,如下所示:

  1. 在指示的第2行,find被设置为false
  2. 第2行和第3行之间没有代码。
  3. 所以到达第3行,!找到的必然是true所以init是不可避免的。

我不知道这是否正确。我隐约记得,编译器优化可以改变语句的执行顺序。这在这里起作用了吗?有没有可能在3号线和4号线之前到达5号线?

环境
openjdk 15.0.2 2021-01-19
openjdk运行时环境(构建15.0.2 7-27)
openjdk 64位服务器虚拟机(构建15.0.2 7-27,混合模式,共享)
javac 15.0.2 Windows 10

共有1个答案

傅浩漫
2023-03-14

请看我(迟到)对另一个问题的回答。规范要求进行源代码分析。

这不是以您建议的方式重新排序代码;这将改变行为,这是被禁止的。

想想一般情况:如果在计算完成之前允许使用计算,那么没有什么是可预测的。

但是,在您的示例中,允许足够聪明的编译器将生成的代码优化为(有效地)System.out.println(-1)。这两个变量实际上都不需要。

如果发生这种情况,则不会影响所需的明确任务检查。从逻辑上讲,简化是在验证源代码之后进行的。

你必须检查生成的字节码,看看实际发生了什么。此外,在Java中,可以“稍后”通过及时编译到本机代码来完成优化。

 类似资料:
  • 问题内容: 输出始终为。 但是,绝对可以使循环多次遍历1s 。 我认为,在闭包是在FUNC。 请参见下面的代码。 在多行“ +1”之后,输出正好是预期的很大数目。 问题答案: 记忆模型 2014年5月31日版本 介绍 Go内存模型指定了一种条件,在这种条件下,可以保证在一个goroutine中读取变量可以观察到在不同goroutine中写入同一变量所产生的值。 忠告 修改由多个goroutine同

  • 我经常遇到这种情况。乍一看,我认为,“这是糟糕的编码;我正在执行一个方法两次,必然会得到相同的结果。”但想到这里,我不得不怀疑编译器是否像我一样聪明,并能得出相同的结论。 编译器的行为是否取决于 方法的内容?假设它看起来像这样(有点类似于我现在的真实代码): 除非对这些对象来自的任何存储进行处理不当的异步更改,否则如果连续运行两次,肯定会返回相同的内容。但是,如果它看起来像这样(为了论证而无意义的

  • 问题内容: 是否可以编译无需重新编译即可在所有Linux发行版中执行的C / C ++源代码? 如果答案是肯定的,我可以使用任何外部(非标准C / C ++)库吗? 我要分发我的二进制应用程序,而不是分发源代码。 问题答案: 不,您不能编译在所有Linux发行版中执行的可执行文件。但是,您可以编译可在人们倾向于关注的大多数发行版上运行的可执行文件。 编译32位。为您愿意支持的最低CPU级别进行编译

  • 我遇到的问题是“是/否”语句,如果我输入“否”,它将继续退出程序。请告诉我问题出在哪里? 导入java。util。随机的导入java。util。扫描仪; 公共类NumberGame{private static final int DO_NOT_PLAY_reach=0; }

  • 问题内容: 我目前正在翻译中编写一个针对Java字节码的玩具编译器。 我想知道是否可以在编写.class文件之前在发出的字节码中进行各种简单的窥孔优化的目录,也许是摘要。我实际上知道一些具有此功能的库,但是我想自己实现。 问题答案: 您知道Proguard吗?http://proguard.sourceforge.net/ 这是一个很棒的字节码优化器,它实现了很多优化。请参阅常见问题解答以获取列表

  • 我一直在做一个倒计时程序,我想到了这个。 在最后的while循环中,如果里面没有print/println语句,倒计时代码就不会执行。为什么?不过,该程序与print语句配合得非常好。