【问题标题】:Java: int array initializes with nonzero elementsJava:int数组用非零元素初始化
【发布时间】:2012-09-01 07:28:35
【问题描述】:

根据 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

【问题讨论】:

  • 如果不遵循规范,我会说实现中的错误
  • 既然你有一个定义明确的例子可以可靠地重现问题(至少在某些平台上),你考虑过filing a bug吗?
  • 是的,您绝对应该提交错误报告。这是一个非常严重的错误!
  • 是的,我已经向 Oracle 发送了错误报告(错误 ID 7196857),它会在几天后出现在公共 Oracle 错误数据库中。
  • 我在 Windows 上用 Java 7 update 7 64-bit 试了一下,没有问题。

标签: java arrays jvm initialization java-7


【解决方案1】:

这里我们遇到了 JIT 编译器中的一个错误。编译器确定分配的数组在Arrays.fill(...) 中分配后被填充,但分配和填充之间的使用检查错误。因此,编译器执行了非法优化 - 它跳过了分配数组的归零。

此错误已放置在 Oracle 错误跟踪器 (bug id 7196857) 中。不幸的是,我没有等待 Oracle 对以下几点做出任何澄清。正如我所看到的,这个错误是特定于操作系统的:它在 64 位 Linux 和 Mac 上绝对可以重现,但是,正如我从 cmets 看到的,它在 Windows 上不经常重现(对于类似版本的 JDK)。此外,很高兴知道何时修复此错误。

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

10 月 5 日更新:

在 2012 年 10 月 4 日发布的 JDK 7u10(抢先体验)的新 Build 10 中,这个 bug 至少在 Linux 操作系统上得到了修复(其他的我没有测试)。感谢@Makoto,他发现这个漏洞在 Oracle 漏洞数据库中不再可供公众访问。不幸的是,我不知道 Oracle 将其从公共访问中删除的原因,但它可以在 Google cache 中找到。此外,这个漏洞引起了 Redhat 的注意:CVE 标识符 CVE-2012-4420 (bugzilla) 和 CVE-2012-4416 (bugzilla) 被分配给这个漏洞。

【讨论】:

【解决方案2】:

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

    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++;
    }

【讨论】:

  • Windows 7 64 位。 JDK 64 位 1.7.0_07
猜你喜欢
  • 2015-01-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-30
  • 2018-11-05
  • 2016-07-15
  • 1970-01-01
  • 2020-03-20
相关资源
最近更新 更多