Ich bin über ein ziemlich seltsames Problem gestolpert, das ich bei der Ausführung von Java 8 erstellen kann. Das Problem tritt auf, als ob irgendeine Art von Timing-Fehler in der JVM selbst auftritt. Es ist intermittierend, aber leicht reproduzierbar (zumindest in meinen Testumgebungen). Das Problem besteht darin, dass ein Array-Wert, der explizit festgelegt wird, zerstört und unter bestimmten Umständen durch eine 0.0 ersetzt wird. Insbesondere wird in dem folgenden Code array[0]
auf 0.0 nach der Zeile new Double(r.nextDouble());
ausgewertet. Wenn Sie dann den Inhalt von array[0]
erneut betrachten, wird der Wert jetzt als der korrekte Wert von 1.0 angezeigt. Beispiel für die Ausgabe dieses Testfalls vom Laufen ist:Java 8 seltsames Timing/Speicherproblem
claims array[0] != 1.0....array[0] = 1.0
claims array[0] now == 1.0...array[0] = 1.0`
Ich bin mit 64-Bit-Windows 7 und ist in der Lage, dieses Problem zu reproduzieren, sowohl innerhalb von Eclipse und wenn von der Kommandozeile kompiliert, mit JDKs 1.8_45, 1.8_51 und 1.8_60. Ich kann das Problem mit 1.7_51 nicht lösen. Die gleichen Ergebnisse wurden auf einer anderen 64-Bit-Windows 7-Box demonstriert.
Dieses Problem erschien in einer großen, nicht-trivialen Software, aber ich konnte es auf ein paar Zeilen Code reduzieren. Im Folgenden finden Sie einen kleinen Testfall, der das Problem veranschaulicht. Es ist ein ziemlich seltsam aussehender Testfall, scheint jedoch alle notwendig zu sein, um den Fehler zu verursachen. Die Verwendung von Random
ist nicht erforderlich - ich kann alle r.nextDouble()
mit jedem doppelten Wert ersetzen und das Problem demonstrieren. Interessanterweise, wenn someArray[0] = .45;
durch someArray[0] = r.nextDouble();
ersetzt wird, konnte ich das Problem nicht replizieren (obwohl es nichts besonderes an .45
gibt). Eclipse-Debugging hilft auch nicht - es ändert das Timing so stark, dass es nicht mehr passiert. Selbst eine gut platzierte System.err.println()
-Anweisung führt dazu, dass das Problem nicht mehr auftritt.
Wieder ist das Problem intermittierend, um das Problem reproduzieren zu können, muss dieser Testfall möglicherweise mehrmals ausgeführt werden. Ich glaube, ich musste es fast 10 mal laufen lassen, bevor ich die oben gezeigte Ausgabe bekomme. In Eclipse gebe ich eine Sekunde oder zwei nach dem Laufen und töte es dann, wenn es nicht passiert ist. Von der Kommandozeile aus - führen Sie es aus, wenn es nicht passiert CTRL+C
zu beenden und erneut versuchen. Es scheint, dass wenn es passieren wird, es ziemlich schnell passiert.
Ich bin in der Vergangenheit auf Probleme wie diese gestoßen, aber sie waren alle Threading-Probleme. Ich kann mir nicht vorstellen, was hier vor sich geht - ich habe mir sogar den Bytecode angesehen (der übrigens zwischen 1.7_51 und 1.8_45 identisch war).
Irgendwelche Ideen, was hier passiert?
import java.util.Random;
public class Test {
Test(){
double array[] = new double[1];
Random r = new Random();
while(true){
double someArray[] = new double[1];
double someArray2 [] = new double [2];
for(int i = 0; i < someArray2.length; i++) {
someArray2[i] = r.nextDouble();
}
// for whatever reason, using r.nextDouble() here doesn't seem
// to show the problem, but the # you use doesn't seem to matter either...
someArray[0] = .45;
array[0] = 1.0;
// commented out lines also demonstrate problem
new Double(r.nextDouble());
// new Float(r.nextDouble();
// double d = new Double(.1) * new Double(.3);
// double d = new Double(.1)/new Double(.3);
// double d = new Double(.1) + new Double(.3);
// double d = new Double(.1) - new Double(.3);
if(array[0] != 1.0){
System.err.println("claims array[0] != 1.0....array[0] = " + array[0]);
if(array[0] != 1.0){
System.err.println("claims array[0] still != 1.0...array[0] = " + array[0]);
}else {
System.err.println("claims array[0] now == 1.0...array[0] = " + array[0]);
}
System.exit(0);
}else if(r.nextBoolean()){
array = new double[1];
}
}
}
public static void main(String[] args) {
new Test();
}
}
Haben Sie nach schlechtem Speicher gesucht? – wero
Ich kann das nicht reproduzieren. Funktioniert wie erwartet hier. – marstran
'double' ist inhärent nicht präzise. Sind Sie sicher, dass dies nicht Ihr Problem ist? –