使用JVM TI技术实现JVM监控

来源:互联网 发布:java c base64 编辑:程序博客网 时间:2024/06/05 02:43

在JAVA单元测试中,需要监控单元测试的覆盖率,记录JAVA代码的执行过程,或者是需要动态插装字节码的应用程序中(例如AOP/IOC技术, 动态插装字节码的技术我将在下一篇的博客中介绍),我们可以使用JVM TI接口进行监控,本程序介绍一种监控JAVA代码的方法,注意:本程序不适合代码量很大的项目,会严重影响程序性能,如果需要开发高性能的监控代码,请参考我的另一篇博客

#include "stdafx.h" #include <jni.h>#include <jni_md.h>#include "windows.h"  #include <jvmti.h> #include <string> #include <cstring> #include <iostream> #include <list> #include <map> #include <set> #include <stdlib.h> #include <jni_md.h> int _tmain(int argc, _TCHAR* argv[]){return 0;}typedef jint (WINAPI *_CreateJavaVM)(JavaVM **, void **, void *); static jvmtiEnv *gb_jvmti = NULL;static jvmtiCapabilities gb_capa;static jrawMonitorID gb_lock; static void   enter_critical_section(jvmtiEnv *jvmti){    jvmtiError error;    error = jvmti->RawMonitorEnter(gb_lock);} static void   exit_critical_section(jvmtiEnv *jvmti){    jvmtiError error;    error = jvmti->RawMonitorExit(gb_lock);} static void JNICALL callbackException(jvmtiEnv *jvmti_env, JNIEnv* env, jthread thr, jmethodID method, jlocation location, jobject exception, jmethodID catch_method, jlocation catch_location) {            enter_critical_section(gb_jvmti);             {                        char *name,*sig,*gsig;                        jvmtiError  error  = gb_jvmti->GetMethodName(method, &name, &sig, &gsig);                        if (error  != JVMTI_ERROR_NONE)                         {                                printf("ERROR:GetMethodName!\n");                                return;                        }                        printf("In Agent: Got an exception from Method: %s\n" ,name );                       // if(strcmp(name,"main")==0)                       // {                                                // }            }            exit_critical_section(gb_jvmti); } JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *jvm, char *options, void *reserved){            jvmtiError error;            jvmtiEventCallbacks callbacks;             jint result = jvm->GetEnv((void **) &gb_jvmti, JVMTI_VERSION_1_0);            if(result != JNI_OK || gb_jvmti==NULL)            {                        printf("ERROR: Unable to access JVMTI!");                        return JNI_ERR;            }             memset(&gb_capa,0,sizeof(jvmtiCapabilities));gb_capa.can_signal_thread = 1;gb_capa.can_get_owned_monitor_info = 1;gb_capa.can_generate_method_entry_events = 1;gb_capa.can_generate_exception_events = 1;gb_capa.can_generate_vm_object_alloc_events = 1;gb_capa.can_tag_objects = 1;               //error = gb_jvmti->AddCapabilities(&gb_capa);           /* if(error != JVMTI_ERROR_NONE)            {                        printf("ERROR: Can't get JVMTI capabilities");                        return JNI_ERR;            }*/            jclass *classes;jint count;error = gb_jvmti->GetLoadedClasses(&count, &classes);if (error) {printf("ERROR: JVMTI GetLoadedClasses failed!\n");}for (int i = 0; i < count; i++) {char *sig;gb_jvmti->GetClassSignature(classes[i], &sig, NULL);if(strcmp(sig,"com/test/VMAttacher")>0){   printf("cls sig=%s\n", sig);}}            memset(&callbacks,0,sizeof(jvmtiEventCallbacks));            callbacks.Exception = &callbackException;             error = gb_jvmti->SetEventCallbacks(&callbacks, sizeof(callbacks));            if(error != JVMTI_ERROR_NONE)            {                        printf("ERROR: Can't set jvmti callback!");                        return JNI_ERR;            }             error = gb_jvmti->CreateRawMonitor("agent data", &gb_lock);            if(error != JVMTI_ERROR_NONE)            {                        printf("ERROR: Can't create raw monitor!");                        return JNI_ERR;            }  //   error = gb_jvmti->SetEventNotificationMode(JVMTI_ENABLE,JVMTI_EVENT_VM_INIT, (jthread)NULL);error = gb_jvmti->SetEventNotificationMode(JVMTI_ENABLE,JVMTI_EVENT_EXCEPTION, (jthread)NULL);          return JNI_OK;} JNIEXPORT void JNICALL Agent_OnUnload(JavaVM *vm){//}


将以上代码编译DLL控件后,再使用javapath或者javalib参数指定该DLL控件作为JAVA Agent启动即可

0 0
原创粉丝点击