Est-ce un bug JVM ou «comportement attendu»?

J’ai remarqué un comportement inattendu (inattendu par rapport à mes attentes personnelles), et je me demandais si quelque chose se produisait s’il y avait un bogue dans la JVM ou s’il s’agissait peut-être d’un cas marginal où je ne comprenais pas certains détails. est censé arriver. Supposons que nous ayons le code suivant dans une méthode principale:

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

Une attente naïve serait que cela imprime Integer.MAX_VALUE-1 , le plus grand même représentant représentable. Cependant, je pense que l’arithmétique entière est supposée “basculer” en Java. L’ajout de 1 à Integer.MAX_VALUE devrait donc entraîner Integer.MIN_VALUE . Comme Integer.MIN_VALUE est toujours inférieur à Integer.MAX_VALUE , la boucle continuerait à parcourir le négatif même ints. Finalement, il reviendrait à 0, et ce processus devrait se répéter en boucle infinie.

Lorsque je lance ce code, j’obtiens des résultats non déterministes. Le résultat imprimé est de l’ordre d’un demi-million, mais la valeur exacte varie. Donc, non seulement la boucle se termine quand je pense que cela devrait être une boucle infinie, mais elle semble se terminer de manière aléatoire. Que se passe-t-il?

Je suppose que c’est soit un bogue dans la JVM, soit il y a beaucoup d’optimisation géniale qui rend ce comportement attendu. Lequel est-ce?

Bug connu Relatif à

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6196102

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6357214

et d’autres.

Je pense qu’ils sont considérés comme peu prioritaires à corriger car ils ne se présentent pas dans le monde réel.

C’est bizarre. Cela ressemble certainement à un bug quelque part. J’obtiens les mêmes résultats à chaque fois avec le même code, mais des modifications sortingviales du code modifient le résultat. Par exemple:

 public class Test { public static void main(Ssortingng[] 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); } } 

... imprime toujours 2147483640 et vrai

alors que ceci:

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

imprime toujours -2147483648 et true.

Très, très bizarre.

(Cela exécute une VM OpenJDK 1.6 sous Linux.)

EDIT: Exécuter OpenJDK 1.7 sur Windows 7, je ne vois pas le problème:

 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) 

Essayez d’append System.out.println(count);

Je me demande s’il y a optimisation parce que count n’est jamais lu.

Edit – une autre réponse a donné le lien vers les bogues dans Oracle Tracker Bug. En tirant de cela:

  • 6196102 mentionne en particulier qu’il existe un bogue de Integer.MAX_VALUEInteger.MAX_VALUE est concerné.
  • Java doit essayer d’optimiser la boucle, car le count n’est jamais lu.

Cependant, il est peu probable que cela se produise dans la pratique, car:

  • Integer.MAX_VALUE est un Integer.MAX_VALUE improbable
  • Habituellement, les boucles ne fonctionnent pas pour permettre cette optimisation en premier lieu

Cela semble être une optimisation de la boucle lorsque j’observe le même résultat, mais si j’imprime aussi le count le résultat change.

C’est à dire

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

Produit 2147483638 tandis que le code original produit 457158 (ou similaire)

 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) 

travailler comme prévu. boucle infinie