介绍

JVMTI(Java Virtual Machine Tool Interface)是一个由Oracle提供的标准接口,

用于在Java虚拟机(JVM)上创建工具和应用程序。允许开发者在运行时监控和修改JVM的行为,

让JVMTI成为进行性能分析、监控、调试和其他类型工具开发的强大工具。

ClassTransformer

本文主要介绍用 JNI_OnLoad 获取 jvmti 进行设置 ClassFileLoadHook 事件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

// 用于将 类重新加载一次,相当于执行一次 ClassFileLoadHook,拿到类的字节
JNIEXPORT void JNICALL retransformClass(JNIEnv *env, jclass caller, jclass target){
jvmti->RetransformClasses(1, &target);
}

// 重新定义 类的字节码
JNIEXPORT void JNICALL redefineClass(JNIEnv *env, jclass caller, jclass target, jbyteArray classBytes){

jvmtiClassDefinition classDef;

classDef.klass = target;
classDef.class_byte_count = env->GetArrayLength(classBytes);
classDef.class_bytes = (unsigned char *)env->GetByteArrayElements(classBytes, NULL);

jvmti->RedefineClasses(1, &classDef);
}

JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved)
{

vm->GetEnv((void **)&jvmti, JVMTI_VERSION_1_1);

jvmtiCapabilities caps;
memset(&caps, 0, sizeof(caps));

// 设置能够使用 classHook 事件
caps.can_generate_all_class_hook_events = 1;
caps.can_retransform_any_class = 1;
caps.can_retransform_classes = 1;
caps.can_redefine_any_class = 1;
caps.can_redefine_classes = 1;
jvmti->AddCapabilities(&caps);

jvmtiEventCallbacks callbacks = {};
callbacks.ClassFileLoadHook = &classFileLoadHook;
jvmti->SetEventCallbacks(&callbacks, sizeof(callbacks));

jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_CLASS_FILE_LOAD_HOOK, nullptr);

return JNI_VERSION_1_8;
}

妈的红温了,不想写了(ctrl+z撤销没了),给个流程图你感受感受

jni function hook

自己感受下,我没话讲了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void redirectMethod() {

// hook register
jniNativeInterface *redirected_jni_Functions;
jvmti->GetJNIFunctionTable(&redirected_jni_Functions);

// ** hook jni method start **

redirected_jni_Functions->CallStaticVoidMethod = &CallStaticVoidMethodHook;


// ** hook jni method end **

//设置钩子
jvmti->SetJNIFunctionTable(redirected_jni_Functions);
}