tabla - Erróneo for-loops en Java?
imprimir una matriz en forma de tabla en java (4)
De acuerdo con los gurús de Java, este es el error 5091921 , corregido en JDK7 pero no planeado para una corrección en JDK6.
Observé un comportamiento erróneo al ejecutar el siguiente código 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);
}
}
}
Ambos bucles hacen exactamente lo mismo. Sin embargo, el segundo genera un valor erróneo no determinista. Estoy ejecutando el código en Linux usando Version:
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)
Muestra de salida:
1073741811
141312
¿Puedes reproducirlo? ¿Es un error?
Editar: Extraño
final int end = Integer.MAX_VALUE - 1;
funciona bien.
Es posible que sea el bucle erróneo que se desenrolla en HotSpot en la máquina virtual del servidor de 64 bits. Intenta ejecutar el código con -client
o +XX:-AggressiveOpts
.
Hay errores que afectan a los bucles específicamente cuando el límite superior está cerca de Integer.MAX_VALUE
.
Ver esta pregunta
Puedo reproducirlo con el archivo .class
producido por Eclipse, pero no al compilar en la línea de comandos con javac
.
El bytecode generado difiere:
salida 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
Para algo más fácil de leer, aquí está la salida de Grimp producida por el Soot :
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;
Salida del compilador 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
Salida de Grimp:
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;
Curiosamente, la versión producida por javac
usa if_icmpge
como una condición de salida (> = 2147483647) en un int
, lo que no debería tener sentido (el igual lo hace, pero no el mayor que). Ambos parecen correctos, así que sospecharía un error de JVM.