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

为什么不可能在Java中创建MAX_INT大小的数组?

莘光华
2023-03-14

我已经阅读了这个问题的一些答案(为什么我不能创建大尺寸的数组https://bugs.openjdk.java.net/browse/JDK-8029587)我不理解以下内容。“在GC代码中,我们将对象的大小以单词的形式传递为int。”据我所知,JVM中单词的大小为4字节。根据这一点,如果我们将单词中的大尺寸长数组(例如MAX_INT-5)的大小作为INT传递,我们必须获得OutOfMemoryException,请求的数组大小超过VM限制,因为即使没有标头大小,对于INT来说,大小也太大。那么,为什么不同类型的数组对元素的最大数量有相同的限制呢?

共有2个答案

钱言
2023-03-14

据我所知,答案在jdk源代码中(我正在查看jdk-9);在写了之后,我也不确定是否应该改为评论(如果它回答了你的问题),但评论太长了。。。

首先,从hotspot/src/share/vm/oops/arrayKlass.cpp抛出错误:

if (length > arrayOopDesc::max_array_length(T_ARRAY)) {
   report_java_out_of_memory("Requested array size exceeds VM limit");
    ....
}

现在,T_ARRAY实际上是基本类型的枚举,如下所示:

public static final BasicType T_ARRAY = new BasicType(tArray);
// tArray is an int with value = 13

这是第一个表明,当计算最大大小时,jdk不关心该数组将容纳什么(T_array没有指定该数组将包含什么类型)。

现在实际验证最大数组大小的方法如下所示:

 static int32_t max_array_length(BasicType type) {
      assert(type >= 0 && type < T_CONFLICT, "wrong type");
      assert(type2aelembytes(type) != 0, "wrong type");

      const size_t max_element_words_per_size_t =
      align_size_down((SIZE_MAX/HeapWordSize - header_size(type)), MinObjAlignment);
      const size_t max_elements_per_size_t =
      HeapWordSize * max_element_words_per_size_t / type2aelembytes(type);
      if ((size_t)max_jint < max_elements_per_size_t) {
         // It should be ok to return max_jint here, but parts of the code
         // (CollectedHeap, Klass::oop_oop_iterate(), and more) uses an int for
         // passing around the size (in words) of an object. So, we need to avoid
         // overflowing an int when we add the header. See CRs 4718400 and 7110613.
         return align_size_down(max_jint - header_size(type), MinObjAlignment);
      }
       return (int32_t)max_elements_per_size_t;
}

我没有深入研究代码,但它是基于HeapWordSize;至少为8字节。这里有一个很好的参考(我试图查找代码本身,但对它的引用太多了)。

尉迟冯浩
2023-03-14

只解决为什么不同类型的数组对最大元素数有相同的限制?零件:

因为在实际现实中没多大关系;但是允许实现JVM的代码更简单。

当只有一个限制时;这对于所有类型的数组都是一样的;然后您可以使用该代码处理所有数组。而不是有很多特定于类型的代码。

考虑到需要“大”数组的人仍然可以创建它们;只有那些需要真正非常大的数组的人才会受到影响;为什么要花这么多精力?

 类似资料:
  • 我正在学习罗伯特·C·马丁(Robert C.Martin)2009年出版的《干净的代码》(Clean Code)一书,我偶然发现了衔接的概念(第10章)。罗伯特引用: 每个方法使用每个变量的类具有最大的内聚性。一般来说,创建这样的最大内聚类既不可取,也不可能。。。 不幸的是,我没有找到详细的解释。有没有人用真实的代码示例来解释这一点? 非常感谢!!

  • 为什么不可能创建最大int大小的数组? 我找到了这样的解释: null

  • 问题内容: 我想做的是这样的: Eclipse中给了我这个编译错误的:。 当我将类设为静态时,该错误消失。我可以使static,但我不明白为什么我不能在内部类中声明一个。 问题答案: 定义为嵌套类型的类型始终是隐式的(请参见JLS§8.9。Enums) 您不能在非静态类型(也就是“内部类”,请参见JLS§8.1.3。内部类和封闭实例)中拥有静态嵌套类型。 因此,您不能在非静态嵌套类型中包含内部类型

  • 问题内容: 这是我正在运行的命令: 另外,我正在使用自制Python运行Mac 这是我的setup.py脚本:https : //gist.github.com/cloudformdesign/4791c46fe7cd52eb61cd 我要疯了-我不知道为什么这不起作用。 问题答案: 首先安装软件包: 文档并不太清楚,但是 “ wheel项目为setuptools提供了bdist_wheel命令”

  • 问题内容: Java中的数组的长度是固定的。Java为什么要允许大小为0的数组呢? 问题答案: 它表示它为空。即您可以遍历它,就好像它有项目并且没有结果发生一样: 从而避免了检查的需要。如果所讨论的数组为,则会发生异常,但是在这种情况下,它什么也不做,这可能是适当的。

  • 我试图创建一个带有可选参数的模板函数,但我很难理解编译失败的原因。这是我的测试(设计)代码: 只有当我用这两个参数调用时,代码才会编译。如果我尝试只传递1个参数,编译将失败,出现以下错误: main.cpp:18:34:错误:调用'GetCountIf' std::cout<<“numelements=”< (我用的是C++14)