ArrayList.add()源码浅析

List<Integer> res = new ArrayList<>();
res.add(1);

add

    /**
     * 增加指定的元素到ArrayList的最后位置
     *
     * @param e 要添加的元素
     * @return
     */
    public boolean add(E e) {
        // 确定ArrayList的容量大小---严谨
        // 注意:size + 1,保证资源空间不被浪费,
        // 按当前情况,保证要存多少个元素,就只分配多少空间资源
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }

ensureCapacityInternal

/**
 * 私有方法:明确 ArrayList 的容量
 * 用于内部优化,保证空间资源不被浪费:尤其在 add() 方法添加时起效
 *
 * @param minCapacity 指定的最小容量
 */
private void ensureCapacityInternal(int minCapacity) {
    ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}

calculateCapacity

private static int calculateCapacity(Object[] elementData, int minCapacity) {
    // 若 elementData == {},则取 minCapacity 为 默认容量和参数 minCapacity 之间的最大值
    // 注:ensureCapacity() 是提供给用户使用的方法,在 ArrayList 的实现中并没有使用
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
        return Math.max(DEFAULT_CAPACITY, minCapacity);
    }
    return minCapacity;
}

ensureExplicitCapacity

/**
 * 私有方法:明确 ArrayList 的容量
 * - 用于内部优化,保证空间资源不被浪费:尤其在 add() 方法添加时起效
 *
 * @param minCapacity 指定的最小容量
 */
private void ensureExplicitCapacity(int minCapacity) {
    // 将“修改统计数”+1,该变量主要是用来实现fail-fast机制的
    modCount++;
    // 防止溢出代码:确保指定的最小容量 > 数组缓冲区当前的长度
    // overflow-conscious code
    if (minCapacity - elementData.length > 0)
        // 分配容量
        grow(minCapacity);
}

grow

/**
 * 私有方法:扩容,以确保 ArrayList 至少能存储 minCapacity 个元素
 * - 扩容计算:newCapacity = oldCapacity + (oldCapacity >> 1);  扩充当前容量的1.5倍
 *
 * @param minCapacity 指定的最小容量
 */
private void grow(int minCapacity) {
    // 防止溢出代码
    int oldCapacity = elementData.length;
    // 运算符 >> 是带符号右移. 如 oldCapacity = 10,则 newCapacity = 10 + (10 >> 1) = 10 + 5 = 15
    int newCapacity = oldCapacity + (oldCapacity >> 1);
    // 若 newCapacity 依旧小于 minCapacity
    if (newCapacity - minCapacity < 0)
        //则直接将 minCapacity 赋值给newCapacity值
        newCapacity = minCapacity;
    // 若 newCapacity 大于最大存储容量,则进行大容量分配
    if (newCapacity - MAX_ARRAY_SIZE > 0)
        newCapacity = hugeCapacity(minCapacity);
     // minCapacity 通常接近 size,所以这是一个胜利:
    elementData = Arrays.copyOf(elementData, newCapacity);
}

hugeCapacity

/**
 * 私有方法:大容量分配,最大分配 Integer.MAX_VALUE
 *
 * @param minCapacity
 */
private static int hugeCapacity(int minCapacity) {
    if (minCapacity < 0) // overflow
        throw new OutOfMemoryError();
    //MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8
    return (minCapacity > MAX_ARRAY_SIZE) ?
            Integer.MAX_VALUE :
            MAX_ARRAY_SIZE;
}

copyOf

/**
 * 复制指定的数组,截断或填充空值(如有必要),
 * 使副本具有指定的长度。对于在原始数组和副本中都有效的所有索引,
 * 这两个数组将包含相同的值。对于在副本中有效但在原始副本中无效的任何索引,
 * 副本将包含 <tt>null<tt>。当且仅当指定长度大于原始数组的长度时,
 * 此类索引才会存在。结果数组与原始数组的类完全相同。
 *
 * @param <T> the class of the objects in the array
 * @param original the array to be copied
 * @param newLength the length of the copy to be returned
 * @return a copy of the original array, truncated or padded with nulls
 *     to obtain the specified length
 * @throws NegativeArraySizeException if <tt>newLength</tt> is negative
 * @throws NullPointerException if <tt>original</tt> is null
 * @since 1.6
 */
@SuppressWarnings("unchecked")
public static <T> T[] copyOf(T[] original, int newLength) {
    return (T[]) copyOf(original, newLength, original.getClass());
}

copyOf

/**
 * 复制指定的数组,截断或填充空值(如有必要),使副本具有指定的长度。
 * 对于在原始数组和副本中都有效的所有索引,这两个数组将包含相同的值。
 * 对于在副本中有效但在原始副本中无效的任何索引,副本将包含 <tt>null<tt>。
 * 当且仅当指定长度大于原始数组的长度时,此类索引才会存在。
 * 结果数组属于 <tt>newType<tt> 类。
 *
 * @param <U> the class of the objects in the original array
 * @param <T> the class of the objects in the returned array
 * @param original the array to be copied
 * @param newLength the length of the copy to be returned
 * @param newType the class of the copy to be returned
 * @return a copy of the original array, truncated or padded with nulls
 *     to obtain the specified length
 * @throws NegativeArraySizeException if <tt>newLength</tt> is negative
 * @throws NullPointerException if <tt>original</tt> is null
 * @throws ArrayStoreException if an element copied from
 *     <tt>original</tt> is not of a runtime type that can be stored in
 *     an array of class <tt>newType</tt>
 * @since 1.6
 */
public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
    @SuppressWarnings("unchecked")
    T[] copy = ((Object)newType == (Object)Object[].class)
        ? (T[]) new Object[newLength]
        : (T[]) Array.newInstance(newType.getComponentType(), newLength);
    System.arraycopy(original, 0, copy, 0,
                     Math.min(original.length, newLength));
    return copy;
}

getComponentType

/**
 * 返回表示数组组件类型的 {@code Class}。如果此类不表示数组类,则此方法返回 null。
 *
 * @return the {@code Class} representing the component type of this
 * class if this class is an array
 * @see     java.lang.reflect.Array
 * @since JDK1.1
 */
public native Class<?> getComponentType();

JVM_GetComponentType

JVM_ENTRY(jclass, JVM_GetComponentType(JNIEnv *env, jclass cls))
  JVMWrapper("JVM_GetComponentType");
  oop mirror = JNIHandles::resolve_non_null(cls);
  oop result = Reflection::array_component_type(mirror, CHECK_NULL);
  return (jclass) JNIHandles::make_local(env, result);
JVM_END

resolve_non_null

inline oop JNIHandles::resolve_non_null(jobject handle) {
  assert(handle != NULL, "JNI handle should not be null");
  oop result = resolve_impl<false /* external_guard */ >(handle);
  assert(result != NULL, "NULL read from jni handle");
  return result;
}

array_component_type

oop Reflection::array_component_type(oop mirror, TRAPS) {
    // 是不是特权
  if (java_lang_Class::is_primitive(mirror)) {
    return NULL;
  }
    // 返回mirror数据地址
  Klass* klass = java_lang_Class::as_Klass(mirror);
    // 是不是一个数组
  if (!klass->oop_is_array()) {
    return NULL;
  }
  // 是一个数组
  // oop      _component_mirror;  // component type, as a java/lang/Class
  // oop  component_mirror() const         { return _component_mirror; }  
  oop result = ArrayKlass::cast(klass)->component_mirror();
#ifdef ASSERT
  oop result2 = NULL;
    // 一维数组
  if (ArrayKlass::cast(klass)->dimension() == 1) {
    if (klass->oop_is_typeArray()) {
      result2 = basic_type_arrayklass_to_mirror(klass, CHECK_NULL);
    } else {
      result2 = ObjArrayKlass::cast(klass)->element_klass()->java_mirror();
    }
  } else {
    // 多维数组
    Klass* lower_dim = ArrayKlass::cast(klass)->lower_dimension(); // 引用第 (n-1) 维数组(如果存在)。
    assert(lower_dim->oop_is_array(), "just checking");
    result2 = lower_dim->java_mirror();
  }
  assert(result == result2, "results must be consistent");
#endif //ASSERT
  return result;
}

as_Klass

Klass* java_lang_Class::as_Klass(oop java_class) {
  //%note memory_2
  assert(java_lang_Class::is_instance(java_class), "must be a Class object");
    // 返回元数据字段的地址
  Klass* k = ((Klass*)java_class->metadata_field(_klass_offset));
  assert(k == NULL || k->is_klass(), "type check");
  return k;
}

metadata_field

// 返回地址
inline Metadata* oopDesc::metadata_field(int offset) const {
  return *metadata_field_addr(offset);
}

cast

// Casting from Klass*
static ArrayKlass* cast(Klass* k) {
  assert(k->oop_is_array(), "cast to ArrayKlass");
  return (ArrayKlass*) k;
}

basic_type_arrayklass_to_mirror

oop Reflection:: basic_type_arrayklass_to_mirror(Klass* basic_type_arrayklass, TRAPS) {
  BasicType type = TypeArrayKlass::cast(basic_type_arrayklass)->element_type();
  return Universe::java_mirror(type);
}

newInstance

/**
 * 创建具有指定组件类型和长度的新数组。调用此方法相当于创建一个数组,如下所示:
 * <blockquote>
 * <pre>
 * int[] x = {length};
 * Array.newInstance(componentType, x);
 * </pre>
 * </blockquote>
 *
 * <p>The number of dimensions of the new array must not
 * exceed 255.
 *
 * @param componentType the {@code Class} object representing the
 * component type of the new array
 * @param length the length of the new array
 * @return the new array
 * @exception NullPointerException if the specified
 * {@code componentType} parameter is null
 * @exception IllegalArgumentException if componentType is {@link
 * Void#TYPE} or if the number of dimensions of the requested array
 * instance exceed 255.
 * @exception NegativeArraySizeException if the specified {@code length}
 * is negative
 */
public static Object newInstance(Class<?> componentType, int length)
    throws NegativeArraySizeException {
    return newArray(componentType, length);
}

newArray

private static native Object newArray(Class<?> componentType, int length)
    throws NegativeArraySizeException;

Java_java_lang_reflect_Array_newArray

JNIEXPORT jobject JNICALL
Java_java_lang_reflect_Array_newArray(JNIEnv *env, jclass ignore,
                                      jclass eltClass, jint length)
{
    return JVM_NewArray(env, eltClass, length);
}

JVM_NewArray

JVM_ENTRY(jobject, JVM_NewArray(JNIEnv *env, jclass eltClass, jint length))
  JVMWrapper("JVM_NewArray");
  JvmtiVMObjectAllocEventCollector oam;
  // 将eltClass地址转为oop
  oop element_mirror = JNIHandles::resolve(eltClass);
  // 反射创建新数组
  oop result = Reflection::reflect_new_array(element_mirror, length, CHECK_NULL);
  return JNIHandles::make_local(env, result);
JVM_END
arrayOop Reflection::reflect_new_array(oop element_mirror, jint length, TRAPS) {
  if (element_mirror == NULL) {
    THROW_0(vmSymbols::java_lang_NullPointerException());
  }
  if (length < 0) {
    THROW_0(vmSymbols::java_lang_NegativeArraySizeException());
  }
  if (java_lang_Class::is_primitive(element_mirror)) {
    Klass* tak = basic_type_mirror_to_arrayklass(element_mirror, CHECK_NULL);
    return TypeArrayKlass::cast(tak)->allocate(length, THREAD);
  } else {
    Klass* k = java_lang_Class::as_Klass(element_mirror);
    if (k->oop_is_array() && ArrayKlass::cast(k)->dimension() >= MAX_DIM) {
      THROW_0(vmSymbols::java_lang_IllegalArgumentException());
    }
    return oopFactory::new_objArray(k, length, THREAD);
  }
}

new_objArray

objArrayOop oopFactory::new_objArray(Klass* klass, int length, TRAPS) {
  assert(klass->is_klass(), "must be instance class");
  if (klass->oop_is_array()) {
    return ((ArrayKlass*)klass)->allocate_arrayArray(1, length, THREAD);
  } else {
    assert (klass->oop_is_instance(), "new object array with klass not an InstanceKlass");
    return ((InstanceKlass*)klass)->allocate_objArray(1, length, THREAD);
  }
}

allocate_arrayArray

objArrayOop ArrayKlass::allocate_arrayArray(int n, int length, TRAPS) {
  if (length < 0) {
    THROW_0(vmSymbols::java_lang_NegativeArraySizeException());
  }
  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());
  }
  int size = objArrayOopDesc::object_size(length);
  Klass* k = array_klass(n+dimension(), CHECK_0);
  ArrayKlass* ak = ArrayKlass::cast(k);
  objArrayOop o =
    (objArrayOop)CollectedHeap::array_allocate(ak, size, length, CHECK_0);
  // initialization to NULL not necessary, area already cleared
  return o;
}
1 Like