Wait GC to complete before each hook
This commit is contained in:
parent
93cea40f85
commit
30e7dfd3d8
|
|
@ -129,4 +129,6 @@ public class Main implements KeepAll {
|
|||
public static native long suspendAllThreads();
|
||||
|
||||
public static native void resumeAllThreads(long obj);
|
||||
|
||||
public static native int waitForGcToComplete(long thread);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package com.elderdrivers.riru.xposed.core;
|
||||
|
||||
import com.elderdrivers.riru.xposed.Main;
|
||||
import com.elderdrivers.riru.xposed.entry.hooker.OnePlusWorkAroundHooker;
|
||||
import com.elderdrivers.riru.xposed.util.Utils;
|
||||
|
||||
|
|
@ -11,6 +12,8 @@ import java.util.Arrays;
|
|||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
import de.robv.android.xposed.XposedHelpers;
|
||||
|
||||
import static com.elderdrivers.riru.xposed.Main.backupAndHookNative;
|
||||
import static com.elderdrivers.riru.xposed.Main.findMethodNative;
|
||||
|
||||
|
|
@ -111,7 +114,14 @@ public class HookMain {
|
|||
if (backup != null) {
|
||||
HookMethodResolver.resolveMethod(hook, backup);
|
||||
}
|
||||
Runtime.getRuntime().gc();
|
||||
// make sure GC completed before hook
|
||||
Thread currentThread = Thread.currentThread();
|
||||
int lastGcType = Main.waitForGcToComplete(
|
||||
XposedHelpers.getLongField(currentThread, "nativePeer"));
|
||||
if (lastGcType < 0) {
|
||||
Utils.logW("waitForGcToComplete failed, using fallback");
|
||||
Runtime.getRuntime().gc();
|
||||
}
|
||||
if (!backupAndHookNative(target, hook, backup)) {
|
||||
throw new RuntimeException("Failed to hook " + target + " with " + hook);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,6 +52,12 @@ void resumeAllThreads(JNIEnv *, jclass, jlong obj) {
|
|||
resumeAll(reinterpret_cast<ScopedSuspendAll *>(obj));
|
||||
}
|
||||
|
||||
int waitForGcToComplete(JNIEnv *, jclass, jlong thread) {
|
||||
// if waitGc succeeded, it should return one of enum collector::GcType
|
||||
int gcType = waitGc(0, reinterpret_cast<void *>(thread));
|
||||
return gcType;
|
||||
}
|
||||
|
||||
static JNINativeMethod hookMethods[] = {
|
||||
{
|
||||
"init",
|
||||
|
|
@ -99,6 +105,9 @@ static JNINativeMethod hookMethods[] = {
|
|||
},
|
||||
{
|
||||
"resumeAllThreads", "(J)V", (void *) resumeAllThreads
|
||||
},
|
||||
{
|
||||
"waitForGcToComplete", "(J)I", (void *) waitForGcToComplete
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -137,7 +146,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, 13);
|
||||
env->RegisterNatives(entry_class, hookMethods, 14);
|
||||
isInited = true;
|
||||
LOGD("RegisterNatives succeed for HookEntry.");
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -28,6 +28,8 @@ static void *(*instrCstBackup)(void *instru) = nullptr;
|
|||
|
||||
void (*deoptMethod)(void *, void *) = nullptr;
|
||||
|
||||
static void (*heapPreForkBackup)(void *) = nullptr;
|
||||
|
||||
bool my_runtimeInit(void *runtime, void *mapAddr) {
|
||||
if (!runtimeInitBackup) {
|
||||
LOGE("runtimeInitBackup is null");
|
||||
|
|
@ -212,17 +214,49 @@ void hookRuntime(int api_level, void *artHandle, void (*hookFun)(void *, void *,
|
|||
}
|
||||
}
|
||||
|
||||
void (*suspendAll)(ScopedSuspendAll*, const char*, bool) = nullptr;
|
||||
void (*resumeAll)(ScopedSuspendAll*) = nullptr;
|
||||
void (*suspendAll)(ScopedSuspendAll *, const char *, bool) = nullptr;
|
||||
|
||||
void (*resumeAll)(ScopedSuspendAll *) = nullptr;
|
||||
|
||||
int (*waitGcInternal)(void *, int, void *) = nullptr;
|
||||
|
||||
void *heap_ = nullptr;
|
||||
|
||||
int waitGc(int gcCause, void *thread) {
|
||||
if (!heap_) {
|
||||
LOGE("heap_ is null");
|
||||
return -1;
|
||||
}
|
||||
return (*waitGcInternal)(heap_, gcCause, thread);
|
||||
}
|
||||
|
||||
static void myHeapPreFork(void *heap) {
|
||||
heap_ = heap;
|
||||
(*heapPreForkBackup)(heap);
|
||||
}
|
||||
|
||||
void getSuspendSyms(int api_level, void *artHandle, void (*hookFun)(void *, void *, void **)) {
|
||||
if (api_level < ANDROID_N) {
|
||||
return;
|
||||
if (api_level >= ANDROID_LOLLIPOP) {
|
||||
waitGcInternal = reinterpret_cast<int (*)(void *, int, void *)>(dlsym(artHandle,
|
||||
"_ZN3art2gc4Heap19WaitForGcToCompleteENS0_7GcCauseEPNS_6ThreadE"));
|
||||
void *heapPreFork = dlsym(artHandle, "_ZN3art2gc4Heap13PreZygoteForkEv");
|
||||
if (!heapPreFork) {
|
||||
LOGE("can't find heapPreFork: %s", dlerror());
|
||||
} else {
|
||||
// a chance to get pointer of the heap
|
||||
(*hookFun)(heapPreFork, reinterpret_cast<void *>(myHeapPreFork),
|
||||
reinterpret_cast<void **>(&heapPreForkBackup));
|
||||
LOGI("heapPreFork hooked.");
|
||||
}
|
||||
}
|
||||
|
||||
if (api_level >= ANDROID_N) {
|
||||
suspendAll = reinterpret_cast<void (*)(ScopedSuspendAll *, const char *, bool)>(dlsym(
|
||||
artHandle,
|
||||
"_ZN3art16ScopedSuspendAllC2EPKcb"));
|
||||
resumeAll = reinterpret_cast<void (*)(ScopedSuspendAll *)>(dlsym(artHandle,
|
||||
"_ZN3art16ScopedSuspendAllD2Ev"));
|
||||
}
|
||||
suspendAll = reinterpret_cast<void (*)(ScopedSuspendAll*,const char*, bool)>(dlsym(artHandle,
|
||||
"_ZN3art16ScopedSuspendAllC2EPKcb"));
|
||||
resumeAll = reinterpret_cast<void (*)(ScopedSuspendAll*)>(dlsym(artHandle,
|
||||
"_ZN3art16ScopedSuspendAllD2Ev"));
|
||||
}
|
||||
|
||||
void install_inline_hooks() {
|
||||
|
|
|
|||
|
|
@ -26,6 +26,8 @@ extern void (*suspendAll)(ScopedSuspendAll *, const char *, bool);
|
|||
|
||||
extern void (*resumeAll)(ScopedSuspendAll *);
|
||||
|
||||
extern int waitGc(int, void *);
|
||||
|
||||
void install_inline_hooks();
|
||||
|
||||
void deoptimize_method(JNIEnv *env, jclass clazz, jobject method);
|
||||
|
|
|
|||
Loading…
Reference in New Issue