JVM TI (JVM Tool Interface) 是用来开发和监测jvm的编程接口。
开发文档:https://docs.oracle.com/javase/8/docs/platform/jvmti/jvmti.html
https://blog.csdn.net/yczz/article/details/39034223
https://blog.csdn.net/ddelphine/article/details/79695947
JVM TI 提供了许多JVM相关的接口,强制GC的接口是:
jvmtiError ForceGarbageCollection(jvmtiEnv* env)
可以在被监测的测试类中定义原生的native方法,然后用C/C++调用JVM TI提供的接口来实现native方法,最后编译成动态链接库.dll(linux系统为 shared object 文件,.so)
编写简单的agent
源码引用头文件#include<jvmti.h>,该头文件在jdk安装目录的include目录下。#include<jni_md.h>,windows系统中该头文件在jdk安装目录include\win32下,linux系统则在相应的include/linux目录下。在编译生成.dll/.so文件时要添加这两个头文件的搜索路径。
ForceGC.c -fPIC -shared -o forceGC.so
具体编译情况依据系统,语言和编译器
linux环境下 ForceGC.c1
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
/**< 此处定义结构体GobalAgentData用于保存jvmtiEnv指针 */
typedef struct{
jvmtiEnv * jvmti;
}GlobalAgentData;
static GlobalAgentData * gdata;
JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *jvm, char * options, void *reserved){
jvmtiEnv * jvmti = NULL;
jvmtiCapabilities capa;
jvmtiError error;
jint result = (*jvm)->GetEnv(jvm,(void**)&jvmti, JVMTI_VERSION_1_2);
if(result != JNI_OK){
printf("ERROR : Unable to access JVMTI! \n");
}
printf("GC_Agent was loaded success.\n");
(void)memset(&capa,0,sizeof(jvmtiCapabilities));
capa.can_tag_objects = 1;
error = (*jvmti)->AddCapabilities(jvmti,&capa);
//将jvmti保存到全局变量
gdata = (GlobalAgentData*)malloc(sizeof(GlobalAgentData));
gdata->jvmti = jvmti;
return JNI_OK;
}
JNIEXPORT void JNICALL Java_Test_forceGC(JNIEnv* env, jclass thisClass){
jvmtiError error = (*(gdata->jvmti))->ForceGarbageCollection(gdata->jvmti);
if (error == NULL){
printf("\nJVM has been forced to GC.\n");
}
}
1 | ForceGC.h |
最后启动agent
java -agentpath:./forceGC.so Test
结果如下: