Java 为什么我的JVM要做一些运行时循环优化,使我的代码出现错误?

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

考虑以下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;
}

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