130

根据 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);
    }

该异常发生在 JVM 执行代码块的编译之后,并且没有-Xint标志出现。此外,该Arrays.fill(...)语句(与此代码中的所有其他语句一样)是必需的,如果不存在,则不会发生异常。很明显,这个可能的错误与一些 JVM 优化有关。这种行为的原因有什么想法吗?

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

更新:
Oracle 在他们的公共错误数据库中发布了这个错误:http ://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7196857

4

2 回答 2

42

Here we are faced with a bug in the JIT-compiler. Compiler determines that the allocated array is filled after allocation in Arrays.fill(...), but the check for uses between the allocation and the fill is faulty. So, compiler performs an illegal optimization - it skips zeroing of allocated array.

This bug is placed in Oracle bug tracker (bug id 7196857). Unfortunately, I did not wait for any clarifications from Oracle about the following points. As I see, this bug is OS-specific: it absolutely reproducible on 64-bit Linux and Mac, but, as I see from comments, it reproduces not regularly on Windows (for similar versions of JDK). Additionally it would be nice to know when this bug will be fixed.

There is only advice at the moment: do not use JDK1.7.0_04 or later if you depend on JLS for newly declared arrays.

Update at October 5:

In the new Build 10 of the JDK 7u10 (early access) released at October 04, 2012, this bug was fixed at least for Linux OS (I did not test for other). Thanks to @Makoto, who found that this bug is no longer available for public access in Oracle bug database. Unfortunately, I do not know for the reasons Oracle removed it from public access, but it is available in Google cache. Also, this bug has caught the attention of Redhat: the CVE identifiers CVE-2012-4420 (bugzilla) and CVE-2012-4416 (bugzilla) were assigned to this flaw.

于 2012-09-11T17:59:15.810 回答
0

我对您的代码进行了一些更改。这不是整数溢出的问题。查看代码,它在运行时抛出异常

    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++;
    }
于 2012-09-09T09:04:38.247 回答