java jvm compiler-optimization integer-overflow

java - ¿Es esto un error de JVM o "comportamiento esperado"?



compiler-optimization integer-overflow (5)

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 este es un caso marginal en el que no entiendo algunos de los detalles de qué exactamente se supone que suceda Supongamos que tenemos el siguiente código en un método principal por sí mismo:

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 esto imprimirá Integer.MAX_VALUE-1 , el mayor 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 . Como Integer.MIN_VALUE aún es 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?



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).

EDITAR: Ejecutando 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)


Esto parece ser una optimización de bucle ya que observo el mismo resultado, pero SI también imprimo mi count entonces el resultado cambia.

Es decir

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 457158 (o similar)


Intente agregar System.out.println(count);

Me pregunto si hay una optimización porque el recuento nunca se lee.

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

  • 6196102 en particular, menciona que hay un error de Integer.MAX_VALUE en Integer.MAX_VALUE .
  • Java debe intentar optimizar el ciclo porque el count nunca se lee.

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

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

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)

trabajando como se esperaba Bucle infinito