2011-03-03 17 views
69

Noté un comportamiento inesperado (inesperado en relación con mis expectativas personales), y me pregunto si hay algo si hay un error en la JVM o si quizás se trata de un caso marginal en el que no entiendo algunos de los detalles de qué se supone que sucederá exactamente Supongamos que tenemos el siguiente código en un método principal por sí mismo:¿Es esto un error de JVM o "comportamiento esperado"?

int i; 
int count = 0; 
for(i=0; i < Integer.MAX_VALUE; i+=2){ 
    count++; 
} 
System.out.println(i++); 

Una expectativa ingenua sería que este imprimiría Integer.MAX_VALUE-1, el más grande, incluso representable int. Sin embargo, creo que se supone que la aritmética de enteros debe "desplazarse" en Java, por lo que agregar 1 a Integer.MAX_VALUE debería dar como resultado Integer.MIN_VALUE. Dado que Integer.MIN_VALUE es aún menor que Integer.MAX_VALUE, el ciclo se mantendrá iterando a través de las entradas par negativas. Finalmente, volvería a 0, y este proceso debería repetirse como un ciclo infinito.

Cuando realmente ejecuto este código, obtengo resultados no deterministas. El resultado que se imprime tiende a ser del orden de medio millón, pero el valor exacto varía. Entonces, no solo termina el ciclo cuando creo que debería ser un ciclo infinito, sino que parece terminar de forma aleatoria. ¿Que esta pasando?

Supongo que esto es un error en la JVM, o hay una gran cantidad de optimización funky que hace que este comportamiento esperado. ¿Cuál es?

+0

¿Esto es todo lo que está en su método principal? –

+0

Sí ... ¿eso importa? –

+0

@Michael: simplemente comprobando que no estaba pasando nada de funky. En mi máquina siempre está imprimiendo 2147483640, pero eso todavía es inesperado. –

Respuesta

4

Trate de añadir System.out.println(count);

Me pregunto si hay optimización se produce porque la cuenta no se lee de.

Editar - otra respuesta dio el enlace a los errores en el rastreador de errores de Oracle. A partir de que:

  • 6196102 en particular, menciona que hay un error en lo que respecta Canonicalización Integer.MAX_VALUE.
  • Java debe intentar optimizar el bucle porque count nunca se lee.

Sin embargo, esto es poco probable que ocurra en la práctica, debido a que:

  • Integer.MAX_VALUE es un guardia de bucle poco probable
  • Por lo general, los bucles hacer un trabajo que no permitiría que esta optimización en el primer lugar
+0

Esto hace que mis pruebas sean consistentes, al menos. Entonces, ¿es un problema de optimización? –

15

Esto es extraño. Ciertamente se ve como un error en alguna parte. Obtengo los mismos resultados cada vez con el mismo código, pero los cambios triviales en el código cambian el resultado. Por ejemplo:

public class Test { 
    public static void main(String[] args) { 
    int i; 
    int count = 0; 
    for (i = 0; i < Integer.MAX_VALUE; i+=2) { 
     count++; 
    } 
    System.out.println(i); 
    System.out.println(i < Integer.MAX_VALUE); 
    } 
} 

... siempre imprime 2147483640 y verdadero

mientras que esto:

public class Test { 
    public static void main(String[] args) { 
    int i; 
    for (i = 0; i < Integer.MAX_VALUE; i+=2) { 
    } 
    System.out.println(i); 
    System.out.println(i < Integer.MAX_VALUE); 
    } 
} 

siempre imprime -2147483648 y verdadero.

Muy, muy raro.

(Eso es ejecutar una VM OpenJDK 1.6 en Linux.)

EDIT: Ejecución de OpenJDK 1.7 en Windows 7, no veo el problema:

java version "1.7.0-ea" 
Java(TM) SE Runtime Environment (build 1.7.0-ea-b78) 
Java HotSpot(TM) Client VM (build 17.0-b05, mixed mode, sharing) 
2

Ésta parece ser una optimizaciones de ciclo mientras observo el mismo resultado, pero si también imprimir count entonces el resultado cambia

I.e.

int i; 
    int count = 0; 
    for(i=0; i < Integer.MAX_VALUE; i+=2){ 
     count++; 
    } 
    System.out.println(count); 
    System.out.println(i++); 

Produce 2147483638 mientras que el código original produce 457.158 (o similar)

0
java version "1.6.0_22" 
Java(TM) SE Runtime Environment (build 1.6.0_22-b04) 
Java HotSpot(TM) Client VM (build 17.1-b03, mixed mode, sharing) 

funcionando como estaba previsto. ciclo infinito

+1

¿eh? ¿¿infinito?? – totten

Cuestiones relacionadas