una tabla ordenada muestra matriz imprimir impresion forma como bordes arreglo 3x3 java for-loop non-deterministic

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.