Java规范 - 什么是“有效”的优化规则

4

我的理解是,只要优化没有观察到违反JLS的效果即为有效。例如,JIT编译器可以在内部循环中优化掉“无意义”的代码。

但我不记得有明确定义这种情况的声明。

是否有人知道Java优化(例如由本机代码编译器执行)何时有效的明确声明(即在JLS或类似文件中)?


通常单线程场景很简单。多线程则比较麻烦,因为可能会出现一些优化,特别是内存读/写的重新排序。允许哪些重新排序取决于内存模型,但我不知道Java标准规定了哪种内存模型。 - CodesInChaos
当然,例如:code_statement; // “valid” optimization - Margus
@CodeInChaos:优化器可以执行任何不会改变程序单线程执行的优化,因此我们可以做很多事情。 - Voo
@CodeInChaos:等等,在.NET中,你只能优化那些不会影响程序多线程执行的东西吗?这将消除相当多非常有用的优化,我对此表示怀疑 - 有任何来源吗?也许只是一个误解,另外,随着Java5和扩展的volatile定义,我不明白Java应该如何拥有更弱的内存模型。 - Voo
@Voo 这并不完全正确。当前的Java确保了一些事情的发生顺序:同步、线程启动、线程加入和易失性强制实施外部可见的发生关系。此外,构造函数保证在调用终结器之前完成。http://java.sun.com/docs/books/jls/third_edition/html/memory.html - Philip JF
显示剩余4条评论
3个回答

3
JLS 和 JVM 规范都规定了任何 Java 语句的行为(或对于 JVM 规范,字节码如何工作等),但它们没有说明该行为应如何发生。两个文档隐含地指出,只要正确实现所规定的抽象行为,任何实现都被视为符合 Java 实现标准。制定抽象标准的主要目的是指定必须在所有实现间共享的可观察行为,而不涉及造成这些行为的详细信息。因此,实现和其优化器允许进行任何必要和适当的操作以使代码运行,只要它们不偏离指定的语义即可。 希望这可以帮助您!

是的...但你能指出规范中讨论可观察行为的地方,并说明什么是可观察的,什么不是可观察的吗?(我的直觉是采取这种方法...但我想要一些明确的确认。) - Stephen C

1

只要编译器优化不会使代码的行为与标准不同,它就是有效的。这适用于所有语言。

我认为没有必要特别说明这一点,因为符合标准的编译器唯一的要求是其行为与标准描述的相同。一个不改变其表现行为的优化显然不会改变它是否符合标准。


也许有。例如,循环的积极优化(甚至将其完全删除)对编写天真基准测试的人是“可观察”的。如果您能指出规范中明确说明此类优化是“有效”的地方,那将是很好的。(我认为它们应该是...) - Stephen C
@Stephen C:优化是可以观察到的(如果它们什么都不做,那它们就没什么意义了),但我相信规范对于执行时间并没有太多说明。只要优化不改变规范所指定的任何内容(我希望执行速度不是其中之一),它们在符合标准方面就没有任何区别。 - Matti Virkkunen
@Stephen C:规范绝对不关心速度,只要观察到的行为(即程序的结果)是正确的,一切都没问题。此外,优化器可以执行任何不会改变单线程程序执行的操作,例如观察循环变量只读不写,并因此用while(true)替换循环 - 这将导致在另一个线程中设置变量的程序出现问题(显然仅当变量不是易失性的时才会出现问题)。 - Voo

1
例如,如此处所述的字符串池是一种优化形式。据我所知,类似的概念也适用于整数和长整数的小值。
也许您可以在这里找到更多有趣的答案,并了解整数池的解释。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接