Ich habe ein unerwartetes Verhalten festgestellt (unerwartet im Verhältnis zu meinen persönlichen Erwartungen) und frage mich, ob etwas in der JVM fehlerhaft ist oder ob dies möglicherweise ein Randfall ist, in dem ich einige Details nicht genau verstehe soll passieren. Angenommen, wir hätten den folgenden Code in einer Hauptmethode für sich:
int i;
int count = 0;
for(i=0; i < Integer.MAX_VALUE; i+=2){
count++;
}
System.out.println(i++);
Eine naive Erwartung wäre, dass dies gedruckt wird Integer.MAX_VALUE-1
, die größte sogar darstellbar int
. Ich glaube jedoch, dass Ganzzahlarithmetik in Java "rollover" soll, daher sollte das Hinzufügen von 1 zu Integer.MAX_VALUE
führen Integer.MIN_VALUE
. Da Integer.MIN_VALUE
immer noch kleiner als ist Integer.MAX_VALUE
, würde die Schleife die negativen geraden Ints weiter durchlaufen. Schließlich würde es auf 0 zurückkehren, und dieser Vorgang sollte sich als Endlosschleife wiederholen.
Wenn ich diesen Code tatsächlich ausführe, erhalte ich nicht deterministische Ergebnisse. Das Ergebnis, das gedruckt wird, liegt in der Regel in der Größenordnung von einer halben Million, aber der genaue Wert variiert. Die Schleife endet also nicht nur, wenn ich glaube, dass es eine Endlosschleife sein sollte, sondern sie scheint zufällig zu enden. Was ist los?
Ich vermute, dass dies entweder ein Fehler in der JVM ist oder dass eine Menge funky Optimierungen stattfinden, die dieses erwartete Verhalten bewirken. Welches ist es?
quelle
Antworten:
Bekannter Fehler. Bezüglich
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6196102
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6357214
und andere.
Ich denke, sie gelten als niedrig zu beheben, weil sie in der realen Welt nicht auftauchen.
quelle
Das ist bizarr. Es sieht auf jeden Fall irgendwo wie ein Käfer aus. Ich erhalte jedes Mal die gleichen Ergebnisse mit dem gleichen Code, aber geringfügige Änderungen am Code ändern das Ergebnis. Zum Beispiel:
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); } }
... druckt immer 2147483640 und wahr
in der Erwägung, dass dies:
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); } }
druckt immer -2147483648 und true.
Sehr, sehr komisch.
(Damit wird eine OpenJDK 1.6-VM unter Linux ausgeführt.)
BEARBEITEN: Wenn Sie OpenJDK 1.7 unter Windows 7 ausführen, sehe ich das Problem nicht:
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)
quelle
Versuchen Sie es hinzuzufügen
System.out.println(count);
Ich frage mich, ob eine Optimierung stattfindet, weil die Anzahl nie gelesen wird.
Bearbeiten - Eine andere Antwort gab den Link zu Fehlern im Fehler-Tracker von Oracle. Daraus schöpfen:
Integer.MAX_VALUE
es darum geht.count
nie gelesen wird.In der Praxis ist dies jedoch unwahrscheinlich, da:
Integer.MAX_VALUE
ist ein unwahrscheinlicher Schleifenschutzquelle
Dies scheint eine Schleifenoptimierung zu sein, da ich das gleiche Ergebnis beobachte, aber wenn ich auch drucke,
count
ändert sich das Ergebnis.Dh
int i; int count = 0; for(i=0; i < Integer.MAX_VALUE; i+=2){ count++; } System.out.println(count); System.out.println(i++);
Erzeugt 2147483638, während der ursprüngliche Code 457158 (oder ähnliches) erzeugt.
quelle
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)
wie erwartet arbeiten. Endlosschleife
quelle