1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
| JVM_ENTRY(jobject, JVM_Clone(JNIEnv* env, jobject handle)) JVMWrapper("JVM_Clone"); Handle obj(THREAD, JNIHandles::resolve_non_null(handle)); const KlassHandle klass (THREAD, obj->klass()); JvmtiVMObjectAllocEventCollector oam;
#ifdef ASSERT // Just checking that the cloneable flag is set correct if (obj->is_javaArray()) { guarantee(klass->is_cloneable(), "all arrays are cloneable"); } else { guarantee(obj->is_instance(), "should be instanceOop"); bool cloneable = klass->is_subtype_of(SystemDictionary::Cloneable_klass()); guarantee(cloneable == klass->is_cloneable(), "incorrect cloneable flag"); } #endif
// Check if class of obj supports the Cloneable interface. // All arrays are considered to be cloneable (See JLS 20.1.5) if (!klass->is_cloneable()) {//这里检查了是否实现了Cloneable接口,如果没实现,会抛出异常CloneNotSupportException。 ResourceMark rm(THREAD); THROW_MSG_0(vmSymbols::java_lang_CloneNotSupportedException(), klass->external_name()); }
// Make shallow object copy const int size = obj->size();//取对象大小 oop new_obj = NULL; if (obj->is_javaArray()) {//如果是数组 const int length = ((arrayOop)obj())->length();//取长度 new_obj = CollectedHeap::array_allocate(klass, size, length, CHECK_NULL);//分配内存,写入元数据信息 } else { new_obj = CollectedHeap::obj_allocate(klass, size, CHECK_NULL);//分配内存,写入元数据信息 } // 4839641 (4840070): We must do an oop-atomic copy, because if another thread // is modifying a reference field in the clonee, a non-oop-atomic copy might // be suspended in the middle of copying the pointer and end up with parts // of two different pointers in the field. Subsequent dereferences will crash. // 4846409: an oop-copy of objects with long or double fields or arrays of same // won't copy the longs/doubles atomically in 32-bit vm's, so we copy jlongs instead // of oops. We know objects are aligned on a minimum of an jlong boundary. // The same is true of StubRoutines::object_copy and the various oop_copy // variants, and of the code generated by the inline_native_clone intrinsic. assert(MinObjAlignmentInBytes >= BytesPerLong, "objects misaligned"); Copy::conjoint_jlongs_atomic((jlong*)obj(), (jlong*)new_obj, (size_t)align_object_size(size) / HeapWordsPerLong);//这一步就是真正的COPY内存块了 // Clear the header new_obj->init_mark();//初始化对象头,里面包含了Hashcode,GC信息,锁信息等,因为拷贝出的对象是一个全新的对象,所以这些信息需要初始化一下。
// Store check (mark entire object and let gc sort it out) BarrierSet* bs = Universe::heap()->barrier_set(); assert(bs->has_write_region_opt(), "Barrier set does not have write_region"); bs->write_region(MemRegion((HeapWord*)new_obj, size));//write_region最终的实现在一个虚方法里,相当于JAVA的抽象方法,博主没找到实现。暂不发表意见。
// Caution: this involves a java upcall, so the clone should be // "gc-robust" by this stage. if (klass->has_finalizer()) {//如果有finalize方法,则需要注册一下。 assert(obj->is_instance(), "should be instanceOop"); new_obj = instanceKlass::register_finalizer(instanceOop(new_obj), CHECK_NULL); }
return JNIHandles::make_local(env, oop(new_obj));//将内存对象转换成JAVA本地对象返回 JVM_END
|