繁体   English   中英

Java中错误的for循环?

[英]Erroneous for-loops in Java?

我观察到运行以下java代码的错误行为:

public class Prototype {
  public static void main(String[] args) {
    final int start = Integer.MAX_VALUE/2;
    final int end = Integer.MAX_VALUE;
    {
      long b = 0;
      for (int i = start; i < end; i++) {
        b++;
      }
      System.out.println(b);
    }
    {
      long b = 0;
      for (int i = start; i < end; i++) {
        b++;
      }
      System.out.println(b);
    }
  }
}

两个循环完全相同。 然而,第二个输出非确定性的错误值。 我正在使用Version在Linux上运行代码:

java version "1.6.0_25"
Java(TM) SE Runtime Environment (build 1.6.0_25-b06)
Java HotSpot(TM) 64-Bit Server VM (build 20.0-b11, mixed mode)

样本输出:

1073741811
141312

你能重现吗? 这是一个错误吗?

编辑:奇怪

final int end = Integer.MAX_VALUE - 1;

工作良好。

我能够使用Eclipse生成的.class文件重现它,但不能在使用javac在命令行上进行javac时重现它。

生成的字节码不同:

javac输出

public static void main(java.lang.String[]);
  Code:
   0:   lconst_0
   1:   lstore_3
   2:   ldc #2; //int 1073741823
   4:   istore  5
   6:   iload   5
   8:   ldc #3; //int 2147483647
   10:  if_icmpge   23
   13:  lload_3
   14:  lconst_1
   15:  ladd
   16:  lstore_3
   17:  iinc    5, 1
   20:  goto    6
   23:  getstatic   #4; //Field java/lang/System.out:Ljava/io/PrintStream;
   26:  lload_3
   27:  invokevirtual   #5; //Method java/io/PrintStream.println:(J)V
   30:  lconst_0
   31:  lstore_3
   32:  ldc #2; //int 1073741823
   34:  istore  5
   36:  iload   5
   38:  ldc #3; //int 2147483647
   40:  if_icmpge   53
   43:  lload_3
   44:  lconst_1
   45:  ladd
   46:  lstore_3
   47:  iinc    5, 1
   50:  goto    36
   53:  getstatic   #4; //Field java/lang/System.out:Ljava/io/PrintStream;
   56:  lload_3
   57:  invokevirtual   #5; //Method java/io/PrintStream.println:(J)V
   60:  return

对于更容易阅读的内容,这里是Soot生成的Grimp输出:

    java.lang.String[] r0;
    long l0, l2;
    int i1, i3;

    r0 := @parameter0;
    l0 = 0L;
    i1 = 1073741823;

 label0:
    if i1 >= 2147483647 goto label1;

    l0 = l0 + 1L;
    i1 = i1 + 1;
    goto label0;

 label1:
    java.lang.System.out.println(l0);
    l2 = 0L;
    i3 = 1073741823;

 label2:
    if i3 >= 2147483647 goto label3;

    l2 = l2 + 1L;
    i3 = i3 + 1;
    goto label2;

 label3:
    java.lang.System.out.println(l2);
    return;

Eclipse编译器输出

public static void main(java.lang.String[]);
  Code:
   0:   ldc #16; //int 1073741823
   2:   istore_1
   3:   ldc #17; //int 2147483647
   5:   istore_2
   6:   lconst_0
   7:   lstore_3
   8:   ldc #16; //int 1073741823
   10:  istore  5
   12:  goto    22
   15:  lload_3
   16:  lconst_1
   17:  ladd
   18:  lstore_3
   19:  iinc    5, 1
   22:  iload   5
   24:  ldc #17; //int 2147483647
   26:  if_icmplt   15
   29:  getstatic   #18; //Field java/lang/System.out:Ljava/io/PrintStream;
   32:  lload_3
   33:  invokevirtual   #24; //Method java/io/PrintStream.println:(J)V
   36:  lconst_0
   37:  lstore_3
   38:  ldc #16; //int 1073741823
   40:  istore  5
   42:  goto    52
   45:  lload_3
   46:  lconst_1
   47:  ladd
   48:  lstore_3
   49:  iinc    5, 1
   52:  iload   5
   54:  ldc #17; //int 2147483647
   56:  if_icmplt   45
   59:  getstatic   #18; //Field java/lang/System.out:Ljava/io/PrintStream;
   62:  lload_3
   63:  invokevirtual   #24; //Method java/io/PrintStream.println:(J)V
   66:  return

虾产量:

    java.lang.String[] r0;
    int i0, i1, i3, i5;
    long l2, l4;

    r0 := @parameter0;
    i0 = 1073741823;
    i1 = 2147483647;
    l2 = 0L;
    i3 = 1073741823;
    goto label1;

 label0:
    l2 = l2 + 1L;
    i3 = i3 + 1;

 label1:
    if i3 < 2147483647 goto label0;

    java.lang.System.out.println(l2);
    l4 = 0L;
    i5 = 1073741823;
    goto label3;

 label2:
    l4 = l4 + 1L;
    i5 = i5 + 1;

 label3:
    if i5 < 2147483647 goto label2;

    java.lang.System.out.println(l4);
    return;

有趣的是, javac生成的版本在int上使用if_icmpge作为退出条件(> = 2147483647),这应该没有意义(等于,但不是大于)。 但两者看起来都是正确的,所以我怀疑是一个JVM错误。

当上限接近Integer.MAX_VALUE时,存在影响for循环的错误。

看到这个问题

根据Java专家的说法 ,这是错误5091921 ,已在JDK7中修复但未计划在JDK6中进行修复。

有可能是在64位服务器VM中的HotSpot中展开错误的循环。 尝试使用-client+XX:-AggressiveOpts运行代码+XX:-AggressiveOpts

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM