Java 8 奇数计时/内存问题
我遇到了一个相当奇怪的问题,我可以在运行Java 8时创建它。问题本身就好像在JVM本身中发生了某种时序错误一样。它本质上是间歇性的,但很容易重现(至少在我的测试环境中)。问题在于,在某些情况下,显式设置的数组值将被销毁并替换为 0.0。具体来说,在下面的代码中,是计算到0.0之后的行。然后,如果您立即再次查看的内容,它现在显示的值是正确的值1.0。运行此测试用例的示例输出为:array[0]
new Double(r.nextDouble());
array[0]
claims array[0] != 1.0....array[0] = 1.0
claims array[0] now == 1.0...array[0] = 1.0`
我运行的是 64 位 Windows 7,并且能够从 Eclipse 内部和从命令行编译时重现此问题,使用 JDKs 1.8_45、1.8_51 和 1.8_60。我无法在运行1.7_51时产生问题。在另一个 64 位 Windows 7 机箱上也演示了相同的结果。
这个问题出现在一个大型的,不平凡的软件中,但我设法将其压缩为几行代码。下面是一个演示该问题的小测试用例。这是一个看起来相当奇怪的测试用例,但似乎都是导致错误所必需的。不需要使用 - 我可以用任何双精度值替换所有值并演示问题。有趣的是,如果替换为 ,我无法复制该问题(尽管没有什么特别之处)。Eclipse调试也无济于事 - 它改变了时间,使其不再发生。即使一个位置恰当的声明也会导致问题不再出现。Random
r.nextDouble()
someArray[0] = .45;
someArray[0] = r.nextDouble();
.45
System.err.println()
同样,这个问题是间歇性的,所以要重现这个问题,可能必须多次运行这个测试用例。我认为在我得到上面显示的输出之前,我必须运行它最多10次。在Eclipse中,我在运行后给它一两秒钟,如果它没有发生,就杀死它。从命令行相同 - 运行它,如果它没有碰巧退出并重试。看起来,如果它要发生,它发生得很快。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();
}
}