Laut JLS sollte ein int
Array unmittelbar nach der Initialisierung mit Nullen gefüllt werden. Ich bin jedoch mit einer Situation konfrontiert, in der dies nicht der Fall ist. Ein solches Verhalten tritt zuerst in JDK 7u4 und auch in allen späteren Updates auf (ich verwende die 64-Bit-Implementierung). Der folgende Code löst eine Ausnahme aus:
public static void main(String[] args) {
int[] a;
int n = 0;
for (int i = 0; i < 100000000; ++i) {
a = new int[10];
for (int f : a)
if (f != 0)
throw new RuntimeException("Array just after allocation: "+ Arrays.toString(a));
Arrays.fill(a, 0);
for (int j = 0; j < a.length; ++j)
a[j] = (n - j)*i;
for (int f : a)
n += f;
}
System.out.println(n);
}
Die Ausnahme tritt auf, nachdem die JVM die Kompilierung des Codeblocks durchgeführt hat, und tritt nicht mit dem -Xint
Flag auf. Darüber hinaus ist die Arrays.fill(...)
Anweisung (wie alle anderen Anweisungen in diesem Code) erforderlich, und die Ausnahme tritt nicht auf, wenn sie nicht vorhanden ist. Es ist klar, dass dieser mögliche Fehler mit einigen JVM-Optimierungen verbunden ist. Irgendwelche Ideen wegen eines solchen Verhaltens?
Update:
Ich sehe dieses Verhalten auf HotSpot 64-Bit-Server-VM, Java-Version von 1.7.0_04 bis 1.7.0_10 unter Gentoo Linux, Debian Linux (beide Kernel 3.0-Version) und MacOS Lion. Dieser Fehler kann immer mit dem obigen Code reproduziert werden. Ich habe dieses Problem nicht mit einem 32-Bit-JDK oder unter Windows getestet. Ich habe bereits einen Fehlerbericht an Oracle gesendet (Fehler-ID 7196857), der in wenigen Tagen in der öffentlichen Oracle-Fehlerdatenbank angezeigt wird.
Update:
Oracle hat diesen Fehler in seiner öffentlichen Fehlerdatenbank veröffentlicht: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7196857
Antworten:
Hier sind wir mit einem Fehler im JIT-Compiler konfrontiert. Der Compiler stellt fest, dass das zugewiesene Array nach der Zuweisung gefüllt
Arrays.fill(...)
ist, die Überprüfung der Verwendung zwischen der Zuordnung und der Füllung jedoch fehlerhaft ist. Der Compiler führt also eine unzulässige Optimierung durch - er überspringt das Nullstellen des zugewiesenen Arrays.Dieser Fehler wird in Oracle Bug Tracker ( Fehler-ID 7196857 ) platziert. Leider habe ich nicht auf Klarstellungen von Oracle zu den folgenden Punkten gewartet. Wie ich sehe, ist dieser Fehler betriebssystemspezifisch: Er ist unter 64-Bit-Linux und Mac absolut reproduzierbar, aber wie ich aus den Kommentaren sehe, wird er unter Windows nicht regelmäßig reproduziert (für ähnliche Versionen von JDK). Außerdem wäre es schön zu wissen, wann dieser Fehler behoben wird.
Derzeit gibt es nur Ratschläge: Verwenden Sie JDK1.7.0_04 oder höher nicht, wenn Sie für neu deklarierte Arrays auf JLS angewiesen sind.
Update am 5. Oktober:
In dem neuen Build 10 des JDK 7u10 (früher Zugriff), das am 04. Oktober 2012 veröffentlicht wurde, wurde dieser Fehler zumindest für Linux-Betriebssysteme behoben (ich habe nicht für andere getestet). Vielen Dank an @Makoto, der festgestellt hat, dass dieser Fehler nicht mehr für den öffentlichen Zugriff in der Oracle-Fehlerdatenbank verfügbar ist. Leider weiß ich nicht, warum Oracle es aus dem öffentlichen Zugriff entfernt hat, aber es ist im Google- Cache verfügbar . Auch dieser Fehler hat die Aufmerksamkeit von Redhat auf sich gezogen: Die CVE-Kennungen CVE-2012-4420 ( Bugzilla ) und CVE-2012-4416 ( Bugzilla ) wurden diesem Fehler zugewiesen.
quelle
Ich habe Ihren Code geändert. Es ist kein Problem des Integer-Überlaufs. Siehe den Code, er löst zur Laufzeit eine Ausnahme aus
quelle