私は、Java 8を実行するときに作成することができる奇妙な問題を実行しました.JVM自体で何らかの種類のタイミングエラーが発生しているかのように問題が発生します。断続的ですが、少なくとも私のテスト環境では再現性があります。問題は、明示的に設定されている配列値が破棄され、特定の状況下で0.0で置き換えられることです。具体的には、以下のコードでarray[0]
は、new Double(r.nextDouble());
の後に0.0と評価されています。次に、すぐにarray[0]
の内容を見ると、値が1.0の正しい値になります。このテストケースを実行しているからの出力例は次のとおりです。Java 8の奇妙なタイミング/メモリの問題
claims array[0] != 1.0....array[0] = 1.0
claims array[0] now == 1.0...array[0] = 1.0`
私はWindows 7の64ビット版を実行しているがとのJDK 1.8_45で、Eclipse内およびコマンドラインからコンパイルするときの両方から、この問題を再現することができています、 1.8_51、および1.8_60。 1.7_51で問題を発生させることができません。別の64ビットWindows 7ボックスでも同じ結果が示されています。
この問題は、大きなソフトウェアでは見られませんでしたが、私は数行のコードに凝縮させました。以下はその問題を示す小さなテストケースです。それはかなり奇妙に見えるテストケースですが、エラーを引き起こすためにはすべてが必要であるようです。 Random
の使用は必須ではありません。r.nextDouble()
をすべて2重の値に置き換えて問題を示すことができます。面白いことに、someArray[0] = .45;
がsomeArray[0] = r.nextDouble();
に置き換えられた場合、問題は再現できませんでした(ただし、.45
については特別なことはありません)。 Eclipseのデバッグも役に立たないので、タイミングがそれ以上変わることはありません。 System.err.println()
ステートメントを配置しても、問題は表示されなくなります。
また、問題は断続的です。問題を再現するには、このテストケースを何回か実行する必要があります。私はそれを実行しなければならなかったほとんどが上記の出力を得る前に約10倍だと思います。 Eclipseでは、実行してから2〜2回してから、それが起こらなければそれを殺す。コマンドラインから同様に実行してください。実行されない場合は、CTRL+C
を終了してもう一度お試しください。それが起こるなら、それはかなり素早く起こると思われる。
私は過去にこのような問題を抱えていましたが、すべてスレッドの問題でした。私はここで何が起こっているのか理解できません - 私はバイトコード(これは1.7_51と1.8_45の間で全く同じです)を見ました。
ここには何が起こっているかに関するアイデアは何ですか?
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();
}
}
悪いメモリをチェックしましたか? – wero
これは再現できません。ここに期待どおりに動作します。 – marstran
'double'は本質的に正確ではありません。これはあなたの問題ではないと確信していますか?それは複数のマシンには、すべての(私は3種類の64ビットWin7の箱の上に再現することができます)悪い記憶を持っているために起こる可能性がありません@wero –