我注意到了一些意想不到的行为(相对于我的个人期望而出乎意料),我想知道JVM中是否存在错误,或者这是否是一个我不了解某些细节的边缘情况应该发生什么。假设我们在main方法中有以下代码:
int i;
int count = 0;
for(i=0; i < Integer.MAX_VALUE; i+=2){
count++;
}
System.out.println(i++);
一个天真的期望是,这将打印Integer.MAX_VALUE-1
,最大甚至可表示int
。但是,我认为整数算术应该在Java中“翻转”,因此向Integer.MAX_VALUE
添加1会导致Integer.MIN_VALUE
。由于Integer.MIN_VALUE
仍然小于Integer.MAX_VALUE
,因此循环将继续迭代负数甚至整数。最终它会回到0,这个过程应该重复为无限循环。
当我实际运行此代码时,我得到了非确定性结果。打印的结果往往大约为50万,但确切的值会有所不同。因此,当我认为它应该是一个无限循环时,不仅循环终止,而且它似乎随机终止。发生了什么事?
我的猜测是,这可能是JVM中的一个错误,或者正在进行大量的时髦优化,这会产生这种预期的行为。这是什么?
答案 0 :(得分:48)
已知错误。与
相关http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6196102
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6357214
和其他人。
我认为它们被认为是低优先级的,因为它们不会出现在现实世界中。
答案 1 :(得分:15)
这很奇怪。它当然看起来像一个错误。每次使用相同的代码我都会得到相同的结果,但代码的微小变化会改变结果。例如:
public class Test {
public static void main(String[] args) {
int i;
int count = 0;
for (i = 0; i < Integer.MAX_VALUE; i+=2) {
count++;
}
System.out.println(i);
System.out.println(i < Integer.MAX_VALUE);
}
}
...始终打印2147483640和true
而这:
public class Test {
public static void main(String[] args) {
int i;
for (i = 0; i < Integer.MAX_VALUE; i+=2) {
}
System.out.println(i);
System.out.println(i < Integer.MAX_VALUE);
}
}
始终打印-2147483648并且为真。
非常非常奇怪。
(那是在Linux上运行OpenJDK 1.6 VM。)
编辑:在Windows 7上运行OpenJDK 1.7,我没有看到问题:
java version "1.7.0-ea"
Java(TM) SE Runtime Environment (build 1.7.0-ea-b78)
Java HotSpot(TM) Client VM (build 17.0-b05, mixed mode, sharing)
答案 2 :(得分:4)
尝试添加System.out.println(count);
我想知道是否存在优化,因为永远不会读取计数。
编辑 - 另一个答案给出了Oracle错误跟踪器中的错误链接。借鉴:
Integer.MAX_VALUE
涉及的规范化错误。count
。然而,这在实践中不太可能发生,因为:
Integer.MAX_VALUE
是一个不太可能的循环保护答案 3 :(得分:2)
这似乎是循环优化,因为我观察到相同的结果,但如果我也打印出count
,那么结果会发生变化。
即
int i;
int count = 0;
for(i=0; i < Integer.MAX_VALUE; i+=2){
count++;
}
System.out.println(count);
System.out.println(i++);
生成2147483638,而原始代码生成457158(或类似)
答案 4 :(得分:0)
java version "1.6.0_22"
Java(TM) SE Runtime Environment (build 1.6.0_22-b04)
Java HotSpot(TM) Client VM (build 17.1-b03, mixed mode, sharing)
按预期工作。无限循环