Java 为什么我的JVM要做一些运行时循环优化,使我的代码出现错误?
考虑以下java代码:Java 为什么我的JVM要做一些运行时循环优化,使我的代码出现错误?,java,macos,jvm,runtime,compiler-optimization,Java,Macos,Jvm,Runtime,Compiler Optimization,考虑以下java代码: public int main() { int i = 1111; for (; rules(i) != true && i < Integer.MAX_VALUE; i++) { //LOG.debug("Testing i: " + i); } System.out.println("The mystery number is: " + i); return i; } protect
public int main() {
int i = 1111;
for (; rules(i) != true && i < Integer.MAX_VALUE; i++) {
//LOG.debug("Testing i: " + i);
}
System.out.println("The mystery number is: " + i);
return i;
}
protected boolean rules(int nb) {
//...
}
返回:
java version "1.6.0_51"
Java(TM) SE Runtime Environment (build 1.6.0_51-b11-456-11M4508)
Java HotSpot(TM) 64-Bit Server VM (build 20.51-b01-456, mixed mode)
尝试用任何其他(未注释的)有效语句替换日志语句,循环也将按预期运行。它绝对是JVM代码优化策略。我认为JVM没有理由无缘无故地在循环中循环。我已经看到了一些关于SO to循环优化的参考资料,这些都是在10000多次迭代之后才出现的。也许这就是为什么“神奇数字”通常在16000左右 这里有一个很好的讨论
不做任何事情循环和条件可以通过JIT编译器进行优化,这就是正在发生的事情 在将其转换为常规Java/main程序(即公共静态void main(String[]args)后,我尝试过这个方法,不要将“main”名称用于其他目的)。我已经将规则(nb)实现为“return false;”它总是停在2147483647。我还尝试过“return Math.random()<0.01”,它平均停止在1200左右,正如几何分布所预测的那样 我认为在您的例子中,rules()中发生了一些事情,javac不能仅仅因为主体是空的就跳过循环,您已经在希望遍历的条件下编写了代码。我写循环,比如:while(DORunThis());它们一直运行,直到方法返回false为止,正如预期的那样 顺便说一下: !!规则(i)比丑陋的规则(i)更紧凑、更优雅真的 也许您并不真正想要:i
for (; !rules ( i ) && i != Integer.MAX_VALUE; i++ );
它还可以计算rules()的最大值。您的另一个选项是在块内运行规则测试。JIT编译器可能会抛出循环,因为它是空的。试着这样做:
public int main() {
int i = 1111;
for (; i < Integer.MAX_VALUE; i++) {
boolean completed = !rules(i);
if (completed) {
break;
}
}
System.out.println("The mystery number is: " + i);
return i;
}
public int main(){
int i=1111;
对于(;i
我在这里遇到了类似的问题:
您应该尝试使用JVM 1.7或尝试使用while循环:
public int main() {
int i = 1111;
while(i < Integer.MAX_VALUE){
if (!rules(i)) {
break;
}
i++
}
System.out.println("The mystery number is: " + i);
return i;
}
public int main(){
int i=1111;
while(i
我使用jdk 1.7.0_21测试了您的代码,它返回了相同的结果942210,无论是否使用LOG.debug语句
int i = 0;
for( ; !rules(i) && i < Integer.MAX_VALUE ; i++ ){
//LOG.debug( "test " + i );
}
System.out.println( "i is " + i );
inti=0;
对于(;!规则(i)&&i
我还打印了两个版本的字节码(空循环)
0:aload\u 0
1:invokespecial#3//方法java/lang/Object。“:()V
4:iconst_0
5:istore_1
6:aload_0
7:iload_1
8:invokevirtual#4//方法规则:(I)Z
11:ifne 26
14:iload_1
15:ldc#5//int 2147483647
17:if_icmpge 26
20:iinc 1,1
23:goto 6
26:getstatic#6//fieldjava/lang/System.out:Ljava/io/PrintStream;
29:new#7//class java/lang/StringBuilder
32:dup
33:invokespecial#8//方法java/lang/StringBuilder。”“:()V
36:ldc#9//字符串i为
38:invokevirtual#10//方法java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
41:iload_1
42:invokevirtual#11//方法java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
45:invokevirtual#12//方法java/lang/StringBuilder.toString:()Ljava/lang/String;
48:invokevirtual#13//方法java/io/PrintStream.println:(Ljava/lang/String;)V
51:返回
带调试打印输出的循环
0: aload_0
1: invokespecial #3 // Method java/lang/Object."<init>":()V
4: iconst_0
5: istore_1
6: aload_0
7: iload_1
8: invokevirtual #4 // Method rules:(I)Z
11: ifne 48
14: iload_1
15: ldc #5 // int 2147483647
17: if_icmpge 48
20: new #6 // class java/lang/StringBuilder
23: dup
24: invokespecial #7 // Method java/lang/StringBuilder."<init>":()V
27: ldc #8 // String test
29: invokevirtual #9 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
32: iload_1
33: invokevirtual #10 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
36: invokevirtual #11 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
39: invokestatic #12 // Method LOG.debug:(Ljava/lang/String;)V
42: iinc 1, 1
45: goto 6
48: getstatic #13 // Field java/lang/System.out:Ljava/io/PrintStream;
51: new #6 // class java/lang/StringBuilder
54: dup
55: invokespecial #7 // Method java/lang/StringBuilder."<init>":()V
58: ldc #14 // String i is
60: invokevirtual #9 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
63: iload_1
64: invokevirtual #10 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
67: invokevirtual #11 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
70: invokevirtual #15 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
73: return
0:aload\u 0
1:invokespecial#3//方法java/lang/Object。“:()V
4:iconst_0
5:istore_1
6:aload_0
7:iload_1
8:invokevirtual#4//方法规则:(I)Z
11:ifne 48
14:iload_1
15:ldc#5//int 2147483647
17:if_icmpge 48
20:new#6//class java/lang/StringBuilder
23:dup
24:invokespecial#7//方法java/lang/StringBuilder。”“:()V
27:ldc#8//字符串测试
29:invokevirtual#9//方法java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
32:iload_1
33:invokevirtual#10//方法java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
36:invokevirtual#11//方法java/lang/StringBuilder.toString:()Ljava/lang/String;
39:invokestatic#12//方法LOG.debug:(Ljava/lang/String;)V
42:iinc 1,1
45:goto 6
48:getstatic#13//fieldjava/lang/System.out:Ljava/io/PrintStream;
51:new#6//class java/lang/StringBuilder
54:dup
55:invokespecial#7//方法java/lang/StringBuilder。”“:()V
58:ldc#14//字符串i为
60:invokevirtual#9//方法java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
63:iload_1
64:invokevirtual#10//方法java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
67:invokevirtual#11//方法java/lang/StringBuilder.toString:()Ljava/lang/String;
70:invokevirtual#15//方法java/io/PrintStream.println:(Ljava/lang/String;)V
73:返回
如您所见,循环结构是相同的。20-39只是co
0: aload_0
1: invokespecial #3 // Method java/lang/Object."<init>":()V
4: iconst_0
5: istore_1
6: aload_0
7: iload_1
8: invokevirtual #4 // Method rules:(I)Z
11: ifne 26
14: iload_1
15: ldc #5 // int 2147483647
17: if_icmpge 26
20: iinc 1, 1
23: goto 6
26: getstatic #6 // Field java/lang/System.out:Ljava/io/PrintStream;
29: new #7 // class java/lang/StringBuilder
32: dup
33: invokespecial #8 // Method java/lang/StringBuilder."<init>":()V
36: ldc #9 // String i is
38: invokevirtual #10 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
41: iload_1
42: invokevirtual #11 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
45: invokevirtual #12 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
48: invokevirtual #13 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
51: return
0: aload_0
1: invokespecial #3 // Method java/lang/Object."<init>":()V
4: iconst_0
5: istore_1
6: aload_0
7: iload_1
8: invokevirtual #4 // Method rules:(I)Z
11: ifne 48
14: iload_1
15: ldc #5 // int 2147483647
17: if_icmpge 48
20: new #6 // class java/lang/StringBuilder
23: dup
24: invokespecial #7 // Method java/lang/StringBuilder."<init>":()V
27: ldc #8 // String test
29: invokevirtual #9 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
32: iload_1
33: invokevirtual #10 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
36: invokevirtual #11 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
39: invokestatic #12 // Method LOG.debug:(Ljava/lang/String;)V
42: iinc 1, 1
45: goto 6
48: getstatic #13 // Field java/lang/System.out:Ljava/io/PrintStream;
51: new #6 // class java/lang/StringBuilder
54: dup
55: invokespecial #7 // Method java/lang/StringBuilder."<init>":()V
58: ldc #14 // String i is
60: invokevirtual #9 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
63: iload_1
64: invokevirtual #10 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
67: invokevirtual #11 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
70: invokevirtual #15 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
73: return