static jobject de_robv_android_xposed_XposedBridge_cloneToSubclassNative(JNIEnv* env, jclass clazz, jobject objIndirect, jclass clzIndirect) { Object* obj = (Object*) dvmDecodeIndirectRef(dvmThreadSelf(), objIndirect); ClassObject* clz = (ClassObject*) dvmDecodeIndirectRef(dvmThreadSelf(), clzIndirect); jobject copyIndirect = env->AllocObject(clzIndirect); if (copyIndirect == NULL) return NULL; Object* copy = (Object*) dvmDecodeIndirectRef(dvmThreadSelf(), copyIndirect); size_t size = obj->clazz->objectSize; size_t offset = sizeof(Object); memcpy((char*)copy + offset, (char*)obj + offset, size - offset); if (IS_CLASS_FLAG_SET(clz, CLASS_ISFINALIZABLE)) dvmSetFinalizable(copy); return copyIndirect; }
/* * Create a copy of an object, for Object.clone(). * * We use the size actually allocated, rather than obj->clazz->objectSize, * because the latter doesn't work for array objects. */ Object* dvmCloneObject(Object* obj, int flags) { assert(dvmIsValidObject(obj)); ClassObject* clazz = obj->clazz; /* Class.java shouldn't let us get here (java.lang.Class is final * and does not implement Clonable), but make extra sure. * A memcpy() clone will wreak havoc on a ClassObject's "innards". */ assert(!dvmIsTheClassClass(clazz)); size_t size; if (IS_CLASS_FLAG_SET(clazz, CLASS_ISARRAY)) { size = dvmArrayObjectSize((ArrayObject *)obj); } else { size = clazz->objectSize; } Object* copy = (Object*)dvmMalloc(size, flags); copy->tag = 0; if (copy == NULL) return NULL; DVM_OBJECT_INIT(copy, clazz); size_t offset = sizeof(Object); /* Copy instance data. We assume memcpy copies by words. */ memcpy((char*)copy + offset, (char*)obj + offset, size - offset); /* Mark the clone as finalizable if appropriate. */ if (IS_CLASS_FLAG_SET(clazz, CLASS_ISFINALIZABLE)) { dvmSetFinalizable(copy); } dvmTrackAllocation(clazz, size); /* notify DDMS */ pthread_mutex_lock(&gDvm.s_mtx); if(gDvm.newObjHook){ gDvm.newObjHook(copy); } pthread_mutex_unlock(&gDvm.s_mtx); return copy; }