久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

JVMTI之HelloWorld - Trema & Colon - 博客大巴

 EverestSnow 2010-04-17

JVMTI之HelloWorld

版權(quán)聲明:轉(zhuǎn)載時(shí)請(qǐng)以超鏈接形式標(biāo)明文章原始出處和作者信息及本聲明
http://trema./logs/1795689.html

JVMTIHelloWorld 

看了一些關(guān)于JVMTI的資料,對(duì)JVMTI的工作原理有了一個(gè)基本的了解,,從SUN給出的文檔來看,,JVMTI將是JVMPIJVMDI等技術(shù)的替代品,并且建議用戶使用JVMTI,,而不是JVMPIJVMDI,,因?yàn)樵谝院蟮?/span>JDK版本中,后兩種技術(shù)可能將不再支持了,。我們希望通過一個(gè)最簡單的HelloWorld程序來講述一下JVMTI編程的一些基本方式,。

1.原理和目標(biāo)。我們的目標(biāo)就是通過JVMTI技術(shù)來監(jiān)控JVM的一些行為,,具體到我們的這個(gè)例子中就是想監(jiān)控JVM中拋出的異常(Exception)事件,。為實(shí)現(xiàn)這一目標(biāo),我們需要編寫一個(gè)Agent動(dòng)態(tài)庫,,在JVM啟動(dòng)的時(shí)候?qū)⒃搫?dòng)態(tài)庫加載進(jìn)去,,在動(dòng)態(tài)庫中需要對(duì)異常(Exception)事件進(jìn)行注冊(cè),使得該類事件發(fā)生時(shí)能觸發(fā)我們編寫的函數(shù),,進(jìn)行相應(yīng)的處理,。所以我們例子中涉及到兩個(gè)部分,一部分是Java編寫的HelloWorld程序,,該程序中會(huì)拋出一個(gè)異常事件,;另一部分是C語言編寫的Agent動(dòng)態(tài)庫,用來監(jiān)控JVM的行為,。

2HelloWorld程序,。這是一個(gè)很簡單的java 程序,在main函數(shù)中打印一條"HelloWorld"字符串,,并拋除一個(gè)Exception異常,。如下:

 

//Sample.java:

class Sample{

public static void main    (String[] orgs){                         

            System.out.println("hello,world");                                   

            String str =null;

            try{

                        str.toString();

            }catch(Exception e)

            {

                        System.out.println("In Java: Got an exception in java code");

            }

}         

}

 

3Agent動(dòng)態(tài)庫,。Agent動(dòng)態(tài)庫在window下為dll文件,在Linux/Unixso文件,,其編寫過程非常簡單:

首先,,在代碼文件中加入”jvmti.h”頭文件,該文件包含在{JDK1.5主目錄}\inlcude目錄下,,它包含了我們所需要用到的一些變量和函數(shù)的定義,。如果編譯時(shí)找不到該頭文件,則應(yīng)該將“{JDK1.5主目錄}\inlcude”和“{JDK1.5主目錄}\inlcude\win32”加入到頭文件的搜索路徑中,。

其次,,實(shí)現(xiàn)Agent_OnLoad()Agent_OnUnload()方法。Agent_Onload()方法在Agent被加載時(shí)調(diào)用,,我們需要在該函數(shù)中完成變量的初始化,,監(jiān)控事件的注冊(cè)等操作,從而使得當(dāng)某類事件發(fā)生時(shí),,JVM能夠通知該Agent,。Agent_Unload()方法在Agent被卸載時(shí)調(diào)用,用來釋放之前申請(qǐng)的內(nèi)存空間,,防止內(nèi)存泄漏,。我們首先需要?jiǎng)?chuàng)建一個(gè)callbackException()函數(shù),并通過SetEventCallbacks()方法將將該函數(shù)進(jìn)行注冊(cè),,使得當(dāng)捕獲到Exception事件時(shí),,能自動(dòng)回調(diào)該函數(shù):

callbacks.Exception = &callbackException;

            error = gb_jvmti->SetEventCallbacks(&callbacks, sizeof(callbacks));

            另外,我們需要通過SetEventNotificationMode()方法來向JVM預(yù)定Exception事件的通知,,讓JVM知道Agent對(duì)該類事件感興趣:

            error= gb_jvmti->SetEventNotificationMode(JVMTI_ENABLE,JVMTI_EVENT_EXCEPTION, (jthread)NULL);

這樣,,當(dāng)JVM運(yùn)行過程發(fā)生Exception事件時(shí),callbackException()函數(shù)就會(huì)被調(diào)用,,我們可以在該函數(shù)中完成自己的一些操作,。在callbackException()函數(shù)中,我們會(huì)判斷捕獲到的Exception是從哪個(gè)方法中拋出的,,如果是“main”方法的話,,就打印出一行字符串:

printf("In Agent: Got an exception from Method: %s\n" ,name );

下面是Agent動(dòng)態(tài)庫的代碼:

 

//MyAgent.cpp:

 

#include

#include

#include

#include "jvmti.h"

 

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;

                        }

                        if(strcmp(name,"main")==0)

                        {

                                    printf("In Agent: Got an exception from Method: %s\n" ,name );

                        }

            }

            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;

            }

           

            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)

{

            //

}

 

 

 

4.編譯執(zhí)行。我是用VC6來編譯Agent動(dòng)態(tài)庫的,,在VC6種創(chuàng)建一個(gè)Win32動(dòng)態(tài)連接庫項(xiàng)目,,取名為MyAgentDll,然后將MyAgent.cpp文件加入該項(xiàng)目,。選擇“工具->選擇->目錄”,,然后將“{JDK1.5主目錄}\inlcude”和“{JDK1.5主目錄}\inlcude\win32加入到“inlcude files”目錄中。然后編譯構(gòu)建MyAgentDll.dll即可,。

            因?yàn)?/span>JVMTIJDK1.5中加入的一項(xiàng)新功能,,所以請(qǐng)先確認(rèn)你所使用的JDK版本:

            #java -version

編譯Sample.java。進(jìn)入Sample所在目錄,,在命令行執(zhí)行如下命令:

            # javac Sample.java

            執(zhí)行Sample,。將MyAgentDll.dll拷貝到Sample.java所在目錄,用如下命令執(zhí)行:

            # java -agentpath:e:\work\jvmit\MyAgentDll.dll Sample

            如果一切順利的話,,應(yīng)該看到如下結(jié)果:

http://image9.360doc.com/DownloadImg/2010/04/1722/2901944_1.jpg

            其中,,“In Agent: Got an exception from Method: main”是Agent打印出來的,其他兩行是Sample.java打印出來的,。

5.結(jié)束語,。我們上面描述的只是一個(gè)非常簡單的JVMTI編程的例子,也是在別人代碼的基礎(chǔ)上修修改改得到的,,它基本上說明了JVMTI編程的大致框架,,如果在其基礎(chǔ)上進(jìn)行一些擴(kuò)充和豐富,就可以做出一些很有用的小工具,。目前一些非常著名的程序性能分析工具,,如JProbe, JRockit, Optimizeit等,雖然不知道其具體的技術(shù)細(xì)節(jié),,但猜想應(yīng)該也是采用了類似的實(shí)現(xiàn)機(jī)制,。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點(diǎn),。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào),。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多