JVM中數組長度限制

發現問題

當寫下這行代碼時,程序會註定運行失敗。html

String strs[] = new String[Integer.MAX_VALUE];

錯誤信息:java.lang.OutOfMemoryError: Requested array size exceeds VM limit.java

並且在jdk源碼中總會看到相似這樣的定義:web

/**
     * The maximum size of array to allocate.
     * Some VMs reserve some header words in an array.
     * Attempts to allocate larger arrays may result in
     * OutOfMemoryError: Requested array size exceeds VM limit
     */
    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

分析問題

看註釋能夠了解到,jvm會爲數組頭信息保留一些空間。官方給出的解釋。咱們去看看jvm內部是如何實現的。數組

objArrayOop ArrayKlass::allocate_arrayArray(int n, int length, TRAPS) {
  //...
  if (length > arrayOopDesc::max_array_length(T_ARRAY)) {
    // 在這拋出異常
    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());
  }
  //...
}

其中, T_ARRAY = 13,表示數據類型。oracle

enum BasicType {
  T_BOOLEAN     =  4,
  T_CHAR        =  5,
  T_FLOAT       =  6,
  T_DOUBLE      =  7,
  T_BYTE        =  8,
  T_SHORT       =  9,
  T_INT         = 10,
  T_LONG        = 11,
  T_OBJECT      = 12,
  T_ARRAY       = 13,
  T_VOID        = 14,
  T_ADDRESS     = 15,
  T_NARROWOOP   = 16,
  T_METADATA    = 17,
  T_NARROWKLASS = 18,
  T_CONFLICT    = 19, // for stack value type with conflicting contents
  T_ILLEGAL     = 99
};

根據數據類型,得到對象頭大小jvm

// Return the maximum length of an array of BasicType.  The length can passed
    // to typeArrayOop::object_size(scale, length, header_size) without causing an
    // overflow. We also need to make sure that this will not overflow a size_t on
    // 32 bit platforms when we convert it to a byte size.
    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_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_down(max_jint - header_size(type), MinObjAlignment);
        }
        return (int32_t)max_elements_per_size_t;
    }

至此咱們瞭解到,jvm中,數組對象的頭上是有一些信息的,這些信息須要佔用必定的空間,因此在java中,新建數組是不能夠指定其大小爲Integer.MAX_VALUE。並且在內存中分配這麼大的對象,在編碼中也是不提倡的。oop

相關文章
相關標籤/搜索