我已经阅读了这个问题的一些答案(Why I can't create an array with large size?和https://bugs.openjdk.java.net/browse/JDK-8029587),我不理解以下内容。 "在GC代码中,我们将单词中对象的大小作为int传递。" 我知道JVM中单词的大小是4个字节。根据这一点,如果我们将大字长数组(例如,MAX_INT - 5)的大小作为int传递,我们必须得到OutOfMemoryException,其中请求的数组大小超过VM限制,因为即使没有标题大小,int的大小也太大了。那么为什么不同类型的数组对元素的最大数量有相同的限制呢?
答案 0 :(得分:2)
只解决为什么不同类型的数组对元素的最大数量有相同的限制?部分:
因为它在实际的现实中并不重要;但允许实现JVM的代码更简单。
当只有一个限制时;各种数组都是一样的;那么你可以使用该代码处理所有数组。而不是拥有很多特定类型的代码。
考虑到需要"大"数组仍然可以创建它们;并且只有那些需要非常大的数组才会受到影响;为什么花这么努力?
答案 1 :(得分:1)
据我所知,答案在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
实际上是BasicType
类型的枚举,如下所示:
public static final BasicType T_ARRAY = new BasicType(tArray);
// tArray is an int with value = 13
这是第一个指示,当计算最大大小时,jdk不会关注该数组将保留的内容(T_ARRAY
没有指定该数组将保留的类型。)< / p>
现在实际验证最大数组大小的方法如下所示:
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 bytes at least
。 here是一个很好的参考(我试着查看代码本身,但是有太多的引用)。