Fix IncompatibleClassChangeError when invoking original method

This commit is contained in:
solohsu 2019-03-12 16:47:25 +08:00
parent 1b68d3fbe0
commit c44086bd0b
5 changed files with 31 additions and 4 deletions

View File

@ -10,6 +10,7 @@ import com.elderdrivers.riru.xposed.proxy.yahfa.BlackWhiteListProxy;
import com.elderdrivers.riru.xposed.proxy.yahfa.NormalProxy;
import com.elderdrivers.riru.xposed.util.Utils;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.util.Arrays;
@ -19,7 +20,6 @@ public class Main implements KeepAll {
public static String appDataDir = "";
public static String niceName = "";
public static String appProcessName = "";
public static long closedFdTable = 0;
private static String forkAndSpecializePramsStr = "";
private static String forkSystemServerPramsStr = "";
@ -105,6 +105,8 @@ public class Main implements KeepAll {
public static native boolean backupAndHookNative(Object target, Method hook, Method backup);
public static native void setMethodNonCompilable(Object member);
public static native void ensureMethodCached(Method hook, Method backup);
// JNI.ToReflectedMethod() could return either Method or Constructor

View File

@ -1,7 +1,10 @@
package com.elderdrivers.riru.xposed.dexmaker;
import android.annotation.TargetApi;
import android.os.Build;
import android.text.TextUtils;
import com.elderdrivers.riru.xposed.Main;
import com.elderdrivers.riru.xposed.core.HookMain;
import java.io.File;
@ -178,6 +181,7 @@ public class HookerDexMaker {
doMake();
}
@TargetApi(Build.VERSION_CODES.O)
private void doMake() throws Exception {
mDexMaker = new DexMaker();
// Generate a Hooker class.
@ -208,6 +212,7 @@ public class HookerDexMaker {
mHookMethod = mHookClass.getMethod(METHOD_NAME_HOOK, mActualParameterTypes);
mBackupMethod = mHookClass.getMethod(METHOD_NAME_BACKUP, mActualParameterTypes);
mCallBackupMethod = mHookClass.getMethod(METHOD_NAME_CALL_BACKUP, mActualParameterTypes);
Main.setMethodNonCompilable(mCallBackupMethod);
HookMain.backupAndHook(mMember, mHookMethod, mBackupMethod);
}

View File

@ -59,6 +59,19 @@ int waitForGcToComplete(JNIEnv *, jclass, jlong thread) {
return gcType;
}
void setMethodNonCompilable(JNIEnv *env, jclass, jobject member) {
if (!member) {
LOGE("setNonCompilableNative: member is null");
return;
}
void *artMethod = env->FromReflectedMethod(member);
if (!artMethod) {
LOGE("setNonCompilableNative: artMethod is null");
return;
}
setNonCompilable(artMethod);
}
static JNINativeMethod hookMethods[] = {
{
"init",
@ -70,6 +83,9 @@ static JNINativeMethod hookMethods[] = {
"(Ljava/lang/Object;Ljava/lang/reflect/Method;Ljava/lang/reflect/Method;)Z",
(void *) Java_lab_galaxy_yahfa_HookMain_backupAndHookNative
},
{
"setMethodNonCompilable", "(Ljava/lang/Object;)V", (void *) setMethodNonCompilable
},
{
"findMethodNative",
"(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object;",
@ -116,7 +132,6 @@ void loadDexAndInit(JNIEnv *env, const char *dexPath) {
if (isInited) {
return;
}
// install_inline_hooks();
jclass clzClassLoader = env->FindClass("java/lang/ClassLoader");
LOGD("java/lang/ClassLoader: %p", clzClassLoader);
jmethodID mdgetSystemClassLoader = env->GetStaticMethodID(clzClassLoader,
@ -147,7 +162,7 @@ void loadDexAndInit(JNIEnv *env, const char *dexPath) {
jclass entry_class = findClassFromLoader(env, myClassLoader, ENTRY_CLASS_NAME);
if (NULL != entry_class) {
LOGD("HookEntry Class %p", entry_class);
env->RegisterNatives(entry_class, hookMethods, 14);
env->RegisterNatives(entry_class, hookMethods, 15);
isInited = true;
LOGD("RegisterNatives succeed for HookEntry.");
} else {

View File

@ -113,7 +113,10 @@ void Java_lab_galaxy_yahfa_HookMain_init(JNIEnv *env, jclass clazz, jint sdkVers
setupTrampoline();
}
static void setNonCompilable(void *method) {
void setNonCompilable(void *method) {
if (SDKVersion < ANDROID_N) {
return;
}
int access_flags = read32((char *) method + OFFSET_access_flags_in_ArtMethod);
LOGI("setNonCompilable: access flags is 0x%x", access_flags);
access_flags |= kAccCompileDontBother;

View File

@ -16,6 +16,8 @@ void Java_lab_galaxy_yahfa_HookMain_ensureMethodCached(JNIEnv *env, jclass clazz
jobject hook,
jobject backup);
void setNonCompilable(void *method);
static void* getResolvedMethodsAddr(JNIEnv*, jobject);
#endif // HOOK_MAIN_H