Java:int数组使用非零元素初始化

Java:int数组使用非零元素初始化,java,arrays,jvm,initialization,java-7,Java,Arrays,Jvm,Initialization,Java 7,根据JLS,初始化之后,int数组应该用零填充。然而,我面临的情况并非如此。这种行为首先发生在JDK 7u4中,并且在所有后续更新中也会发生(我使用64位实现)。以下代码引发异常: public static void main(String[] args) { int[] a; int n = 0; for (int i = 0; i < 100000000; ++i) { a = new int[10];

根据JLS,初始化之后,
int
数组应该用零填充。然而,我面临的情况并非如此。这种行为首先发生在JDK 7u4中,并且在所有后续更新中也会发生(我使用64位实现)。以下代码引发异常:

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);
    }
publicstaticvoidmain(字符串[]args){
int[]a;
int n=0;
对于(int i=0;i<100000000;++i){
a=新整数[10];
for(int f:a)
如果(f!=0)
抛出新的RuntimeException(“分配后的数组:“+Arrays.toString(a));
数组。填充(a,0);
对于(int j=0;j
异常发生在JVM编译代码块之后,并且不使用
-Xint
标志出现。此外,
Arrays.fill(…)
语句(与此代码中的所有其他语句一样)是必需的,如果不存在,则不会发生异常。很明显,这个可能的bug受到一些JVM优化的限制。对这种行为的原因有什么想法吗

更新:
我在HotSpot 64位服务器VM、Gentoo Linux、Debian Linux(内核3.0版本)和MacOS Lion上的Java版本从1.7.0_04到1.7.0_10上看到了这种行为。使用上述代码始终可以重现此错误。我没有在32位JDK或Windows上测试这个问题。我已经向Oracle发送了一份错误报告(错误id 7196857),它将在几天后出现在Oracle的公共错误数据库中

更新:

Oracle在其公共错误数据库中发布了此错误:

我对您的代码做了一些更改。 这不是整数溢出的问题。请参阅代码,它在运行时引发异常

    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));
            }
        }
        for (int ii = 0, len = a.length; ii < len; ii++)
            a[ii] = 0;
        for (int j = 0; j < a.length; ++j)
            a[j] = Integer.MAX_VALUE - 1;
        for (int j = 0; j < a.length; ++j)
            n++;
    }
int[]a;
int n=0;
对于(int i=0;i<100000000;++i){
a=新整数[10];
for(int f:a){
如果(f!=0){
抛出新的RuntimeException(“分配后的数组:“+Arrays.toString(a));
}
}
对于(int ii=0,len=a.length;ii
在这里,我们面临JIT编译器中的一个错误。编译器确定在
数组中分配后填充了分配的数组。填充(…)
,但检查分配和填充之间的使用是错误的。所以,编译器执行了一个非法的优化——它跳过了已分配数组的归零

此bug位于Oracle bug tracker()中。不幸的是,我没有等待Oracle对以下几点的澄清。正如我所看到的,这个bug是特定于操作系统的:它在64位Linux和Mac上绝对可以复制,但是,正如我在评论中看到的,它在Windows上不经常复制(对于类似版本的JDK)。另外,如果能知道这个bug什么时候会被修复,那就太好了

目前只有一条建议:如果新声明的阵列依赖JLS,请不要使用JDK1.7.0_04或更高版本

十月五日更新:


在2012年10月4日发布的JDK 7u10(早期访问)的新版本中,这个错误至少在Linux操作系统中得到了修复(我没有对其他操作系统进行测试)。感谢@Makoto,他发现Oracle bug数据库中的此bug不再可供公众访问。不幸的是,我不知道甲骨文将其从公共访问中删除的原因,但它可以在谷歌上获得。此外,这个bug引起了Redhat的注意:CVE标识符()和()被分配给了这个漏洞。

如果它没有遵循规范,我会说实现中的bug,因为您有一个定义良好的示例,可以可靠地再现问题(至少在某些平台上),您考虑过吗?是的,你应该提交一份bug报告。这是一个非常严重的错误!是的,我已经向Oracle发送了一份错误报告(错误id 7196857),它将在几天后出现在Oracle的公共错误数据库中。我在Windows上使用Java 7 update 7 64位进行了尝试,但没有问题。Windows 7 64位。Jdk 64位1.7.0bug ID现在无效-你能检查一下吗?@Makoto我很困惑,因为这个bug昨天在bug数据库中。我不知道Oracle从公共访问中删除此错误的原因。但谷歌还记得,这个bug也被放在RedHat bug数据库中,因为它可能导致CVE