您的位置 首页 java

java的数组最大可以容纳多少个元素

如题图,库函数里的数组最大数量都是指定为Integer.MAX_VALUE-8。按注释所说,8是为对象头预留的,对象头在64位虚拟机下占16个字节,8一定不是指字节数,如果指的是字长,那么这个数字应该是可以更小的。

找到分配数组的代码

 typeArrayOop TypeArrayKlass::allocate_common(int length, bool do_zero, TRAPS) {
  assert(log2_element_size() >= 0, "bad scale");
  if (length >= 0) {
    if (length <= max_length()) {  //看这里
      size_t size = typeArrayOopDesc::object_size(layout_helper(), length);
      KlassHandle h_k(THREAD, this);
      typeArrayOop t;
      CollectedHeap* ch = Universe::heap();
      if (do_zero) {
        t = (typeArrayOop)CollectedHeap::array_allocate(h_k, (int)size, length, CHECK_NULL);
      } else {
        t = (typeArrayOop)CollectedHeap::array_allocate_nozero(h_k, (int)size, length, CHECK_NULL);
      }
      return t;
    } else {
      report_java_out_of_memory("Requested array size exceeds VM limit");
      JvmtiExport::post_array_size_exhausted();
      THROW_OOP_0(Universe::out_of_memory_error_array_size());
    }
  } else {
    THROW_0(vmSymbols::java_lang_NegativeArraySizeException());
  }
}
  

可以注意到 length 大于max_length()的时候就会抛出Requested array size exceeds VM limit异常,而这个max_length是在初始化的时候设置的:

 TypeArrayKlass::TypeArrayKlass(BasicType type, Symbol* name) : ArrayKlass(name) {
  set_layout_helper(array_layout_helper(type));
  assert(is_array_klass(), "sanity");
  assert(is_typeArray_klass(), "sanity");

  set_max_length(arrayOopDesc::max_array_length(type)); //看这里
  assert(size() >= TypeArrayKlass::header_size(), "bad size");

  set_class_loader_data(ClassLoaderData::the_null_class_loader_data());
}
  

计算过程:

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

而这个SIZE_MAX是一个较为巨大的数字:

 #define SIZE_MAX  UINT64_MAX
#define UINT64_MAX        18446744073709551615ULL
  

所以最后都会落到这里:

    return align_size_down(max_jint - header_size(type), MinObjAlignment);
  

此时:MinObjAlignment值为1,align_size_down这个宏可以忽略。

header_size即为对象头所占的字长(对齐/不对齐):

 static int header_size(BasicType type) {
    size_t typesize_in_bytes = header_size_in_bytes();
    return (int)(Universe::element_type_should_be_aligned(type)
      ? align_object_offset(typesize_in_bytes/HeapWordSize)
      : typesize_in_bytes/HeapWordSize);
  }
  

基础类型只有Double和Long需要对齐:

 inline bool Universe::element_type_should_be_aligned(BasicType type) {
  return type == T_DOUBLE || type == T_LONG;
}
  

对齐的函数:(可以简单理解为字长+1取偶数部分)

 #define align_size_up_(size, alignment) (((size) + ((alignment) - 1)) & ~((alignment) - 1))  

所以数组最大的大小即为:Integer.MAX_VALUE-对象头占的字长。

以64位开启压缩指针为例:markword占8个字节,klass指针4个字节,数组长度4个字节,一共是16个字节(两个)字长。

 public class Hello {
    public static void main(String[] args) {
        Object[] o = new Object[Integer.MAX_VALUE-2];
    }
}  

运行:java -Xmx9000m -Xmn10m Hello,不会有任何异常。

假如关掉压缩指针,klass指针占8个字节,对象头一共8+8+4,再加上补齐,一共是3个字长,那么此时最大数组大小就是Integer.MAX_VALUE-3了。

 $ java -Xmx9000m -Xmn10m -XX:-UseCompressedOops Hello
Exception in thread "main" java.lang.OutOfMemoryError: Requested array size exceeds VM limit
        at Hello.main(Hello.java:4)  

32位虚拟机数组的对象头:markword占4个字节,klass指针占4个字节,数组长度占4个字节,一共是3个字长。在不需要对齐的情况下数组最大最小为Integer.MAX_VALUE-3,而在需要对齐的情况下就是Integer.MAX_VALUE-4。(这一个没有验证,因为我没有装32位的jdk…)

文章来源:智云一二三科技

文章标题:java的数组最大可以容纳多少个元素

文章地址:https://www.zhihuclub.com/190502.shtml

关于作者: 智云科技

热门文章

网站地图