java jvmti
JVM TI(Java Virtual Machine Tool Interface)是 Java 虚拟机工具接口,它为开发工具提供了一种与 Java 虚拟机交互的机制。JVM TI 允许工具在 Java 应用程序运行时监控和控制虚拟机的行为,例如调试、性能分析、代码覆盖率分析等。
JVM TI 核心概念
1. 事件(Events)
JVM TI 定义了一系列事件,这些事件在虚拟机运行时触发,例如方法进入、方法退出、线程启动、线程结束等。工具可以通过注册这些事件来获取虚拟机的运行信息。
2. 能力(Capabilities)
JVM TI 提供了一系列能力,工具需要明确声明它需要哪些能力。例如,某些能力允许工具在运行时修改字节码、获取线程信息等。工具在初始化时需要通过 JVM_OnLoad 函数请求这些能力。
3. 代理(Agent)
代理是一个与 Java 应用程序一起运行的本地库(通常是 .dll 或 .so 文件)。代理通过 JVM TI 与虚拟机交互,监听事件并执行工具逻辑。
4. 函数表(Function Table)
JVM TI 提供了一个函数表,其中包含了所有可以调用的函数。工具通过这个函数表来调用 JVM TI 提供的功能。
JVM TI 主要函数
以下是 JVM TI 中一些常用的函数及其用途:
1. JVM_OnLoad
这是代理加载时调用的入口函数。工具需要在这个函数中初始化 JVM TI 环境,请求能力,并注册事件。
JNIEXPORT jint JNICALL
Agent_OnLoad(JavaVM *vm, char *options, void *reserved) {
jvmtiEnv *jvmti = NULL;
vm->GetEnv((void**)&jvmti, JVMTI_VERSION_1_2);
if (jvmti == NULL) {
return JNI_ERR;
}
// 请求能力
jvmtiCapabilities capabilities;
memset(&capabilities, 0, sizeof(capabilities));
capabilities.can_generate_method_entry_events = 1;
jvmti->AddCapabilities(&capabilities);
// 注册事件
jvmtiEventCallbacks callbacks;
memset(&callbacks, 0, sizeof(callbacks));
callbacks.MethodEntry = &method_entry_callback;
jvmti->SetEventCallbacks(&callbacks, sizeof(callbacks));
jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_METHOD_ENTRY, (jthread)NULL);
return JNI_OK;
}
2. JVM_OnUnload
这是代理卸载时调用的函数。工具可以在该函数中清理资源。
JNIEXPORT void JNICALL
Agent_OnUnload(JavaVM *vm) {
// 清理逻辑
}
3. SetEventNotificationMode
用于启用或禁用事件通知。
jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_METHOD_ENTRY, (jthread)NULL);
4. GetStackTrace
获取线程的堆栈信息。
jvmtiFrameInfo frames[100];
jint count;
jvmti->GetStackTrace(thread, 0, 100, frames, &count);
5. GetLoadedClasses
获取虚拟机中加载的所有类。
jclass classes[100];
jint count;
jvmti->GetLoadedClasses(&count, classes);
6. GetClassSignature
获取类的签名。
char *signature;
char *generic;
jvmti->GetClassSignature(cls, &signature, &generic);
7. GetMethodLocation
获取方法的字节码位置。
jlocation start_location;
jlocation end_location;
jvmti->GetMethodLocation(method, &start_location, &end_location);
示例:方法入口事件监听
以下是一个完整的示例,展示如何使用 JVM TI 监听方法入口事件。
1. 编写代理代码
#include <jvmti.h>
#include <string.h>
#include <stdio.h>
// 方法入口事件回调函数
void JNICALL method_entry_callback(jvmtiEnv *jvmti, JNIEnv* jni_env, jthread thread, jmethodID method) {
char *method_name;
char *method_signature;
char *class_signature;
jclass declaring_class;
jvmti->GetMethodName(method, &method_name, &method_signature, NULL);
jvmti->GetMethodDeclaringClass(method, &declaring_class);
jvmti->GetClassSignature(declaring_class, &class_signature, NULL);
printf("Method Entry: %s::%s%s\n", class_signature, method_name, method_signature);
jvmti->Deallocate((unsigned char*)method_name);
jvmti->Deallocate((unsigned char*)method_signature);
jvmti->Deallocate((unsigned char*)class_signature);
}
// 代理加载函数
JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *vm, char *options, void *reserved) {
jvmtiEnv *jvmti = NULL;
vm->GetEnv((void**)&jvmti, JVMTI_VERSION_1_2);
if (jvmti == NULL) {
return JNI_ERR;
}
// 请求能力
jvmtiCapabilities capabilities;
memset(&capabilities, 0, sizeof(capabilities));
capabilities.can_generate_method_entry_events = 1;
jvmti->AddCapabilities(&capabilities);
// 注册事件
jvmtiEventCallbacks callbacks;
memset(&callbacks, 0, sizeof(callbacks));
callbacks.MethodEntry = &method_entry_callback;
jvmti->SetEventCallbacks(&callbacks, sizeof(callbacks));
// 启用方法入口事件
jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_METHOD_ENTRY, (jthread)NULL);
return JNI_OK;
}
// 代理卸载函数
JNIEXPORT void JNICALL Agent_OnUnload(JavaVM *vm) {
// 清理逻辑
}
2. 编译代理
将上述代码保存为 method_entry_agent.c,然后使用以下命令编译为动态库:
javac -h . MethodEntryAgent.java
gcc -shared -fpic -o libmethod_entry_agent.so -I${JAVA_HOME}/include -I${JAVA_HOME}/include/linux method_entry_agent.c
3. 运行 Java 应用程序
运行 Java 应用程序时,加载代理:
java -agentpath:/path/to/libmethod_entry_agent.so -jar your_application.jar
JVM TI 的其他功能
JVM TI 提供的功能非常丰富,除了上述提到的事件监听和信息获取之外,还包括:
- 字节码注入:通过
RetransformClasses和RedefineClasses函数,可以在运行时修改类的字节码。 - 线程控制:可以挂起、恢复线程,获取线程状态等。
- 内存管理:可以跟踪对象分配、垃圾回收等。
- 性能分析:可以通过
GetTimerInfo和GetTime函数获取高精度计时器信息,用于性能分析。
总结
JVM TI 是一个强大的工具接口,它为开发工具提供了与 Java 虚拟机交互的能力。通过 JVM TI,工具可以监控虚拟机的运行状态、修改字节码、跟踪线程和内存等。
更多推荐




所有评论(0)