- JDK:jdk1.8.0_11
- OpenJDK:openjdk-8u40-src-b25-10_feb_2015
public static native void arraycopy(Object src, int srcPos,Object dest, int destPos,int length);
-
打开openjdk\hotspot\src\share\vm\prims\jvm.cpp可以看到一个方法JVM_ArrayCopy,但是该方法没有真正实现复制的代码,而是简单的检测源数组和目的数组不为空,排除一些异常情况 /* java.lang.System中的arraycopy方法 */ JVM_ENTRY(void, JVM_ArrayCopy(JNIEnv *env, jclass ignored, jobject src, jint src_pos, jobject dst, jint dst_pos, jint length)) JVMWrapper("JVM_ArrayCopy"); // Check if we have null pointers //检查源数组和目的数组不为空 if (src == NULL || dst == NULL) { THROW(vmSymbols::java_lang_NullPointerException()); }
arrayOop s = arrayOop(JNIHandles::resolve_non_null(src)); arrayOop d = arrayOop(JNIHandles::resolve_non_null(dst)); assert(s->is_oop(), "JVM_ArrayCopy: src not an oop"); assert(d->is_oop(), "JVM_ArrayCopy: dst not an oop"); // Do copy //真正调用复制的方法 s->klass()->copy_array(s, src_pos, d, dst_pos, length, thread); JVM_END
-
openjdk\hotspot\src\share\vm\oops\objArrayKlass.cpp文件中copy_array方法
/*
java.lang.System中的arraycopy方法具体实现
*/
void ObjArrayKlass::copy_array(arrayOop s, int src_pos, arrayOop d,int dst_pos, int length, TRAPS) {//检测s是数组assert(s->is_objArray(), "must be obj array");//目的数组不是数组对象的话,则抛出ArrayStoreException异常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.//length==0则不需要复制if (length==0) {return;}//UseCompressedOops只是用来区分narrowOop和oop,具体2者有啥区别需要再研究//调用do_copy函数来复制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);}
}
- do_copy方法
// 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 arrayKlass* 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//stype对象是bound,或者stype是bound的子类抑或stype实现bound接口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 checkT* 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 nowbool 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);
}
- 在openjdk\hotspot\src\share\vm\utilities\copy.hpp文件中找到该conjoint_oops_atomic函数,还有针对narrowOop的重载函数,这里不写出 // oops,conjoint, atomic on each oop
static void conjoint_oops_atomic(oop* from, oop* to, size_t count) {assert_params_ok(from, to, LogBytesPerHeapOop);pd_conjoint_oops_atomic(from, to, count);}
- openjdk\hotspot\src\share\vm\oops\klass.hpp中的is_subtype_of函数
//检测是否是k的子类,或者是实现k接口
bool is_subtype_of(Klass* k) const {juint off = k->super_check_offset();Klass* sup = *(Klass**)( (address)this + off );const juint secondary_offset = in_bytes(secondary_super_cache_offset());if (sup == k) {return true;} else if (off != secondary_offset) {return false;} else {return search_secondary_supers(k);}}
- openjdk\hotspot\src\os_cpu\windows_x86\vm\copy_windows_x86.inline.hpp,最主要就是pd_conjoint_oops_atomic函数
static void pd_conjoint_oops_atomic(oop* from, oop* to, size_t count) {// Do better than this: inline memmove body NEEDS CLEANUPif (from > to) {while (count-- > 0) {// Copy forwards*to++ = *from++;}} else {from += count - 1;to += count - 1;while (count-- > 0) {// Copy backwards*to-- = *from--;}}
}