当前位置: 首页 > 知识库问答 >
问题:

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

姜弘新
2023-03-14

根据 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优化有关。对于这种行为的原因有什么想法吗?

更新:< br >我在Gentoo Linux、Debian Linux(均为内核3.0版本)和MacOS Lion上的HotSpot 64位服务器VM、从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

共有2个答案

吕和风
2023-03-14

我对你的代码做了一些更改。这不是整数溢出的问题。看到代码了吗,它在运行时抛出了一个异常

    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++;
    }
文嘉禧
2023-03-14

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

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

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

10月5日更新:

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

 类似资料:
  • 问题内容: 根据JLS,数组应在初始化后立即用零填充。但是,我面临的情况并非如此。这种行为首先在JDK 7u4中发生,并且在以后的所有更新中也发生(我使用64位实现)。以下代码引发异常: 该异常在JVM执行代码块的编译之后发生,并且不会出现带有标志的异常。此外,该语句(与该代码中的所有其他语句一样)是必需的,并且如果不存在该异常,则不会发生。显然,此可能的错误与JVM优化有关。对于这种行为有什么想

  • 我在中用C创建了一个包含10个元素的数组,并仅为其中一些元素声明了值。当打印出数组时,我注意到其中一个元素(保持不变)没有初始化为零。相反,每次都将其初始化为不同的大值(即)。然后,我注释掉了所有代码,只保留了最初声明的数组。 运行代码时,数组的前8个元素被初始化为零,数组中的第9个元素被初始化为一个大值(如),该值每次都会更改,最后一个元素被一致地初始化为相同的非零数字。 有人知道为什么会这样吗

  • 问题内容: 在我以前做 …将我所有的数组元素初始化为0。 Java中是否有类似的快捷方式? 我想避免使用循环,可以吗? 问题答案: 语言规范保证整数类型数组的默认值为0 : 每个类变量,实例变量或数组组件在创建时都会用 默认值 初始化(第15.9节,第15.10节)。[…]对于type ,默认值为零,即。 如果要将一维数组初始化为其他值,则可以使用java.util.Arrays.fill()(当

  • 本文向大家介绍C#中数组初始化与数组元素复制的方法,包括了C#中数组初始化与数组元素复制的方法的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了C#中数组初始化与数组元素复制的方法。分享给大家供大家参考。具体如下: 下面的代码演示如何创建和初始化数组,以及C#中如何将数组元素从一个复制到另外一个的方法。 代码运行输出结果如下: 希望本文所述对大家的C#程序设计有所帮助。

  • 之间有区别吗 和 ? 两者都起作用,结果完全相同。哪一个更快或更好?有推荐的款式指南吗?

  • 问题内容: 在bash中以这种方式声明数组是否会将所有数组元素初始化为0? 如果没有,如何将数组元素初始化为0? 问题答案: 您的示例将声明/初始化一个空数组。 如果要初始化数组成员,请执行以下操作: 如果要初始化具有100个成员的数组,可以执行以下操作: 请记住,bash中的数组不是固定长度的(索引也不必是连续的)。因此,除非知道数字应为多少,否则无法初始化数组的 所有 成员。