[help wanted] Hooking ClassLoader
Miha-x64 opened this issue · 4 comments
Hello. Thanks for your work!
I'm trying to instrument currently running ClassLoader to profile class loading time, but seeing very small number of loaded classes in logs. Looks like my code gets called only for reflectively loaded classes. What am I doing wrong?
final class ClassLoaderHooks {
private static final String TAG = "ClassLoaderHooks";
static void install() {
try {
AndHook.ensureNativeLibraryLoaded(null);
XposedHelpers.findAndHookMethod(
ClassLoader.class, "loadClass", String.class, boolean.class,
// or BaseDexClassLoader.class, "findClass", String.class,
new Hooks()
);
} catch (Throwable t) {
throw new RuntimeException(t);
}
}
private static final class Hooks extends XC_MethodHook {
private final Map<String, Boolean> loadedClasses = new ConcurrentHashMap<>();
private final ThreadLocal<Stack<Long>> time = new ThreadLocal<>();
@Override
protected void beforeHookedMethod(MethodHookParam param) {
Stack<Long> stack = time.get();
if (stack == null) {
time.set(stack = new Stack<>());
}
stack.push(System.nanoTime());
}
@Override
protected void afterHookedMethod(MethodHookParam param) {
long start = time.get().pop();
long diff = System.nanoTime() - start;
String className = (String) param.args[0];
if (loadedClasses.put(className, Boolean.TRUE) != null) {
return; // already loaded
}
int diffUs = (int) (diff / 1000);
Log.e(TAG, "spent " + (diffUs / 1000.0) + "ms loading type " + className);
}
}
}
Thank you.
Note that ClassLoader.loadClass
is not always necessary to load a class, you can try intercepting DexFile_defineClassNative
or ClassLinker->DefineClass
.
Thank you.
I've found defineClassNative
in C++ source code, it is exposed to JNI, but there's no corresponding Java native
method.
Please consider dalvik/system/DexFile.defineClassNative
FYI, for ones who found this using search.
Found this method using reflection: private static native java.lang.Class dalvik.system.DexFile.defineClassNative(java.lang.String,java.lang.ClassLoader,java.lang.Object,dalvik.system.DexFile) throws java.lang.ClassNotFoundException,java.lang.NoClassDefFoundError
.
Hooks are still getting called rarely.