diff --git a/modules/mogo-module-common/src/main/cpp/method-hook-lib.cpp b/modules/mogo-module-common/src/main/cpp/method-hook-lib.cpp index 046981c7f2..dd5111ea23 100644 --- a/modules/mogo-module-common/src/main/cpp/method-hook-lib.cpp +++ b/modules/mogo-module-common/src/main/cpp/method-hook-lib.cpp @@ -17,37 +17,48 @@ static struct { /** * 替换指定类中的方法 * @param env - * @param type 要替换方法的目标 class + * @param type * @param srcMethodObj 目标方法对象 * @param destMethodObj 替换的方法对象 * @return */ static jlong methodHook(JNIEnv *env, jclass type, jobject srcMethodObj, jobject destMethodObj) { + // 反射:获取了Java对象的在native层的 ArtMethod指针 void *srcMethod = reinterpret_cast(env->FromReflectedMethod(srcMethodObj)); void *destMethod = reinterpret_cast(env->FromReflectedMethod(destMethodObj)); + // 定义存储方法ID的数组 int *backupMethod = new int[methodHookClassInfo.methodSize]; + // 使用的内存拷贝函数 + // 将旧方法ID拷贝到数组中 memcpy(backupMethod, srcMethod, methodHookClassInfo.methodSize); + // 将新方法替换到旧方法地址上 memcpy(srcMethod, destMethod, methodHookClassInfo.methodSize); + // 将旧方法ID返回给java层,用来做方法还原使用 return reinterpret_cast(backupMethod); } /** * 恢复指定类中的方法 * @param env - * @param type 要恢复方法的目标 class + * @param type * @param srcMethod 目标方法对象 * @param methodPtr * @return */ static jobject methodRestore(JNIEnv *env, jclass type, jobject srcMethod, jlong methodPtr) { + // 要还原的旧方法 指针 int *backupMethod = reinterpret_cast(methodPtr); + // 获取了Java对象的在native层的 ArtMethod指针 void *artMethodSrc = reinterpret_cast(env->FromReflectedMethod(srcMethod)); + // 将旧方法指针,替换到 artMethodSrc 中 memcpy(artMethodSrc, backupMethod, methodHookClassInfo.methodSize); + // 删除旧方法备份指针 delete[]backupMethod; + // 返回旧方法 return srcMethod; } - +// 定义要注册的方法 static JNINativeMethod gMethods[] = { { "hook_native", @@ -74,13 +85,17 @@ JNI_OnLoad(JavaVM *vm, void *reserved) { if (vm->GetEnv((void **) &env, JNI_VERSION_1_4) != JNI_OK) { return JNI_FALSE; } + // 加载指定java class jclass classEvaluateUtil = env->FindClass(kClassMethodHookChar); + // 注册 if (env->RegisterNatives(classEvaluateUtil, gMethods, sizeof(gMethods) / sizeof(gMethods[0])) < 0) { return JNI_FALSE; } + // 获取 MethodHook m1、m2 的方法ID methodHookClassInfo.m1 = env->GetStaticMethodID(classEvaluateUtil, "m1", "()V"); methodHookClassInfo.m2 = env->GetStaticMethodID(classEvaluateUtil, "m2", "()V"); + // 获取artMethod的大小, methodHookClassInfo.methodSize = reinterpret_cast(methodHookClassInfo.m2) - reinterpret_cast(methodHookClassInfo.m1); return JNI_VERSION_1_4; diff --git a/modules/mogo-module-common/src/main/java/com/mogo/module/common/hook/MethodHook.java b/modules/mogo-module-common/src/main/java/com/mogo/module/common/hook/MethodHook.java index e63cf11392..8586ac1adc 100644 --- a/modules/mogo-module-common/src/main/java/com/mogo/module/common/hook/MethodHook.java +++ b/modules/mogo-module-common/src/main/java/com/mogo/module/common/hook/MethodHook.java @@ -23,6 +23,12 @@ public class MethodHook { // 备份目标替换方法ID private long backupMethodPtr; + /** + * hook方法 + * + * @param src 要替换的方法对象 + * @param dest 被替换的方法对象 + */ public MethodHook(Method src, Method dest) { srcMethod = src; hookMethod = dest; @@ -30,12 +36,18 @@ public class MethodHook { hookMethod.setAccessible(true); } + /** + * 调用 native 层,完成替换 + */ public void hook() { if (backupMethodPtr == 0) { backupMethodPtr = hook_native(srcMethod, hookMethod); } } + /** + * 调用 native 层,完成方法还原 + */ public void restore() { if (backupMethodPtr != 0) { restore_native(srcMethod, backupMethodPtr); @@ -43,7 +55,16 @@ public class MethodHook { } } - public void callOrigin(Object receiver, Object... args) throws InvocationTargetException, IllegalAccessException { + /** + * 调用原来class 对象中的方法 + * + * @param receiver 接受对象 + * @param args 方法列表 + * @throws InvocationTargetException + * @throws IllegalAccessException + */ + public void callOrigin(Object receiver, Object... args) + throws InvocationTargetException, IllegalAccessException { if (backupMethodPtr != 0) { restore(); srcMethod.invoke(receiver, args); @@ -53,11 +74,26 @@ public class MethodHook { } } + /** + * 调用 native 方法完成 方法替换 + * + * @param src 旧方法 + * @param dest 新方法 + * @return 就方法ID + */ private static native long hook_native(Method src, Method dest); + /** + * 调用 native 方法完成 方法还原 + * + * @param src + * @param methodPtr + * @return + */ private static native Method restore_native(Method src, long methodPtr); static { + // 加载本地方法 so System.loadLibrary("method-hook-lib"); }