/**
* appends the specified element to the end of this list.
*
* @param e element to be appended to this list
* @return <tt>true</tt> (as specified by {@link collection#add})
*/
public boolean add(e e) {
ensurecapacityinternal(size + 1); // increments modcount!!
elementdata[size++] = e;
return true;
}
有时候也使用 void add(int index, e element) 把元素插入到指定的index上. 在jdk中的实现是:
/**
* inserts the specified element at the specified position in this
* list. shifts the element currently at that position (if any) and
* any subsequent elements to the right (adds one to their indices).
*
* @param index index at which the specified element is to be inserted
* @param element element to be inserted
* @throws indexoutofboundsexception {@inheritdoc}
*/
public void add(int index, e element) {
rangecheckforadd(index);
ensurecapacityinternal(size + 1); // increments modcount!!
system.arraycopy(elementdata, index, elementdata, index + 1,
size - index);
elementdata[index] = element;
size++;
}
void objarrayklass::copy_array(arrayoop s, int src_pos, arrayoop d,
int dst_pos, int length, traps) {
assert(s->is_objarray(), "must be obj array");
if (!d->is_objarray()) {
throw(vmsymbols::java_lang_arraystoreexception());
}
// check is all offsets and lengths are non negative
if (src_pos < 0 || dst_pos < 0 || length < 0) {
throw(vmsymbols::java_lang_arrayindexoutofboundsexception());
}
// check if the ranges are valid
if ( (((unsigned int) length + (unsigned int) src_pos) > (unsigned int) s->length())
|| (((unsigned int) length + (unsigned int) dst_pos) > (unsigned int) d->length()) ) {
throw(vmsymbols::java_lang_arrayindexoutofboundsexception());
}
// special case. boundary cases must be checked first
// this allows the following call: copy_array(s, s.length(), d.length(), 0).
// this is correct, since the position is supposed to be an 'in between point', i.e., s.length(),
// points to the right of the last element.
if (length==0) {
return;
}
if (usecompressedoops) {
narrowoop* const src = objarrayoop(s)->obj_at_addr<narrowoop>(src_pos);
narrowoop* const dst = objarrayoop(d)->obj_at_addr<narrowoop>(dst_pos);
do_copy<narrowoop>(s, src, d, dst, length, check);
} else {
oop* const src = objarrayoop(s)->obj_at_addr<oop>(src_pos);
oop* const dst = objarrayoop(d)->obj_at_addr<oop>(dst_pos);
do_copy<oop> (s, src, d, dst, length, check);
}
}
// either oop or narrowoop depending on usecompressedoops.
template <class t> void objarrayklass::do_copy(arrayoop s, t* src,
arrayoop d, t* dst, int length, traps) {
barrierset* bs = universe::heap()->barrier_set();
// for performance reasons, we assume we are that the write barrier we
// are using has optimized modes for arrays of references. at least one
// of the asserts below will fail if this is not the case.
assert(bs->has_write_ref_array_opt(), "barrier set must have ref array opt");
assert(bs->has_write_ref_array_pre_opt(), "for pre-barrier as well.");
if (s == d) {
// since source and destination are equal we do not need conversion checks.
assert(length > 0, "sanity check");
bs->write_ref_array_pre(dst, length);
copy::conjoint_oops_atomic(src, dst, length);
} else {
// we have to make sure all elements conform to the destination array
klass* bound = objarrayklass::cast(d->klass())->element_klass();
klass* stype = objarrayklass::cast(s->klass())->element_klass();
if (stype == bound || stype->is_subtype_of(bound)) {
// elements are guaranteed to be subtypes, so no check necessary
bs->write_ref_array_pre(dst, length);
copy::conjoint_oops_atomic(src, dst, length);
} else {
// slow case: need individual subtype checks
// note: don't use obj_at_put below because it includes a redundant store check
t* from = src;
t* end = from + length;
for (t* p = dst; from < end; from++, p++) {
// xxx this is going to be slow.
t element = *from;
// even slower now
bool element_is_null = oopdesc::is_null(element);
oop new_val = element_is_null ? oop(null)
: oopdesc::decode_heap_oop_not_null(element);
if (element_is_null ||
(new_val->klass())->is_subtype_of(bound)) {
bs->write_ref_field_pre(p, new_val);
*p = element;
} else {
// we must do a barrier to cover the partial copy.
const size_t pd = pointer_delta(p, dst, (size_t)heapoopsize);
// pointer delta is scaled to number of elements (length field in
// objarrayoop) which we assume is 32 bit.
assert(pd == (size_t)(int)pd, "length field overflow");
bs->write_ref_array((heapword*)dst, pd);
throw(vmsymbols::java_lang_arraystoreexception());
return;
}
}
}
}
bs->write_ref_array((heapword*)dst, length);
}
/**
* increases the capacity to ensure that it can hold at least the
* number of elements specified by the minimum capacity argument.
*
* @param mincapacity the desired minimum capacity
*/
private void grow(int mincapacity) {
// overflow-conscious code
int oldcapacity = elementdata.length;
int newcapacity = oldcapacity + (oldcapacity >> 1);
if (newcapacity - mincapacity < 0)
newcapacity = mincapacity;
if (newcapacity - max_array_size > 0)
newcapacity = hugecapacity(mincapacity);
// mincapacity is usually close to size, so this is a win:
elementdata = arrays.copyof(elementdata, newcapacity);
}