<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    posts - 156,  comments - 601,  trackbacks - 0

     

       如果大家有遇到過Java內(nèi)存泄露問題,而且親自動手去定位和分析經(jīng)歷的同學(xué)來講,獲取Java的堆內(nèi)信息對了內(nèi)存使用情況的問題分析和定位是非常有幫助了。例如我們常用的MAT工具,可以較方便的讓我們定位程序中內(nèi)存的使用情況,是哪塊導(dǎo)致了內(nèi)存的泄露等。

        但由于傳統(tǒng)的分析過程比較麻煩,需要使用Jdkjmap(Java Memory Map)命令把heap內(nèi)存dump到一個文件,然后用MAT進(jìn)行分析。所以本文介紹一種方法可以實(shí)現(xiàn)在線查看heap內(nèi)存的使用情況,并附上源碼實(shí)現(xiàn),希望對大家有幫助。由于目前調(diào)研中只找到了Sun JDK6以及以上版本的實(shí)現(xiàn),所以目前該方案只支持Sun JDK6或以上。如果其他同學(xué)有其它版本的JDK實(shí)現(xiàn)分享,歡迎一起交流。

    整體實(shí)現(xiàn)思路如下:

    1.       JDK6中在tools.jar類庫里有一個com.sun.tools.attach.VirtualMachine類,該類可以獲得JVM虛擬機(jī)的相關(guān)控制權(quán)限。

    2.       利用getPids.exe或其它工具獲取需要監(jiān)控的JVM pid進(jìn)程號信息

    3.       利用反射調(diào)用VirtualMachineattach方法,獲取VirtualMachine的實(shí)例對象

    4.       復(fù)用反射調(diào)用VirtualMachine實(shí)例的heapHisto方法,參數(shù)為 –all, 可獲到JVM的堆內(nèi)存信息

    5.       最后解析heapHisto方法返回的輸入流,讀取內(nèi)存數(shù)據(jù)即可獲得當(dāng)前JVM的堆內(nèi)存數(shù)據(jù)

    下面帖出的主要代碼來說明各步驟具體實(shí)現(xiàn)方法:

    JDK6中在tools.jar類庫里有一個com.sun.tools.attach.VirtualMachine類,該類可以獲得JVM虛擬機(jī)的相關(guān)控制權(quán)限。

        private static Class<?> findVirtualMachineClass() throws ClassNotFoundException,

               MalformedURLException {

           // JVM 虛擬機(jī)操作類

           final String virtualMachineClassName = "com.sun.tools.attach.VirtualMachine";

           try {

               return Class.forName(virtualMachineClassName);

           } catch (final ClassNotFoundException e) {

               // exception ignored, try looking else where

               File file = new File(System.getProperty("java.home"));

               if ("jre".equalsIgnoreCase(file.getName())) {

                  file = file.getParentFile();

               }

               //直接從JDK lib目錄下加載 tools.jar類庫

               final String[] defaultToolsLocation = { "lib", "tools.jar" };

               for (final String name : defaultToolsLocation) {

                  file = new File(file, name);

               }

               final URL[] urls = { file.toURI().toURL() };

               final ClassLoader cl = URLClassLoader.newInstance(urls);

               //再次嘗試反射查詢 JVM虛擬機(jī)操作類

               return Class.forName(virtualMachineClassName, true, cl);

           }

    }

     

    利用反射調(diào)用VirtualMachineattach方法,獲取VirtualMachine的實(shí)例對象

    本過程相對比較簡單,獲取VirtualMachine的類后,根據(jù)反射類,查詢attach方法

    //獲取JVM 虛擬機(jī)操作類后

    final Class<?> virtualMachineClass = findVirtualMachineClass();

    //根據(jù)反射查詢 attach方法,參數(shù)為String類型

    final Method attachMethod = virtualMachineClass.getMethod("attach", String.class);

    //通過 getpids.exe工具獲取當(dāng)前JVM進(jìn)程號

    final String pid = PID.getPID();

    try {

        //通過反射調(diào)用attache方法

        jvmVirtualMachine = invoke(attachMethod, null, pid);

    } finally {

        enabled = jvmVirtualMachine != null;

    }

     

    復(fù)用反射調(diào)用VirtualMachine實(shí)例的heapHisto方法,參數(shù)為 –all, 可獲到JVM的堆內(nèi)存信息

    本過程也是利用反射調(diào)用heapHisto方法,實(shí)現(xiàn)的代碼如下:

    final Class<?> virtualMachineClass = getJvmVirtualMachine().getClass();

    //反射調(diào)用 heapHisto方法,參數(shù)為 -all

    final Method heapHistoMethod = virtualMachineClass.getMethod("heapHisto",

           Object[].class);

    //該方面返回值為InputStream

    return (InputStream) invoke(heapHistoMethod, getJvmVirtualMachine(),

                       new Object[] { new Object[] { "-all" } });

     

     

    最后解析heapHisto方法返回的輸入流,讀取內(nèi)存數(shù)據(jù)即可獲得當(dāng)前JVM的堆內(nèi)存數(shù)據(jù), 通過該方法返回的一個文本內(nèi)容。

    Input Stream取出的結(jié)果(文本內(nèi)容)示例如下:

     

     num     #instances         #bytes class name

    ----------------------------------------------

       1:         14948        1892768 [C

       2:           958         567568 [B

       3:          1870         215584 <symbolKlass>

       4:          7366         176784 java.lang.String

       5:           132          88104 [I

       6:           841          86360 <constMethodKlass>

       7:           841          67672 <methodKlass>

       8:           968          61152 [Ljava.lang.Object;

       9:           101          48152 <constantPoolKlass>

      10:          2593          41488 java.lang.StringBuilder

      11:           101          40600 <instanceKlassKlass>

      12:           952          30464 java.util.TreeMap$Entry

      13:            79          25112 <constantPoolCacheKlass>

      14:           310          22280 [S

      15:           746          17904 sun.jvmstat.perfdata.monitor.AliasFileParser$Token

      16:           367          17616 java.nio.HeapCharBuffer

     

    Total         39840        3645336

     

    null

     

    因?yàn)閮?nèi)容太長,只截取了部分

    因?yàn)樽x取的是文本內(nèi)容,而且格式是完全固定的,所以大家可以直接解析里面的內(nèi)容。主要是后面三例,一個是實(shí)現(xiàn)的個數(shù),一個是實(shí)際的數(shù)據(jù)內(nèi)容,最后一個是實(shí)例關(guān)聯(lián)的類名稱.

     



     Good Luck!
     Yours Matthew!






    posted on 2013-02-20 16:30 x.matthew 閱讀(6320) 評論(9)  編輯  收藏 所屬分類: Best Practise(JDK API)
    主站蜘蛛池模板: 久久精品a亚洲国产v高清不卡| 亚洲成人免费在线| 亚洲一级免费毛片| 永久免费A∨片在线观看| 一级毛片直播亚洲| 亚洲精品无码久久一线| 亚洲天堂中文字幕在线观看| 天堂亚洲国产中文在线| 免费黄色毛片视频| 久久久青草青青国产亚洲免观 | 亚洲人成人伊人成综合网无码| 成人黄色免费网站| 久久亚洲色一区二区三区| 国产精品无码永久免费888| 中文字幕不卡免费高清视频| 午夜国产精品免费观看| 亚洲国产成人一区二区三区| 日本免费污片中国特一级| 青青青国产色视频在线观看国产亚洲欧洲国产综合 | 毛片免费全部播放一级| 亚洲经典千人经典日产| 亚洲国产精品一区二区九九| 亚洲天堂电影在线观看| 一本无码人妻在中文字幕免费| 亚洲色大成网站www永久网站| 国产一区二区三区免费看| 中文字幕不卡免费视频| 亚洲伊人久久大香线蕉在观| 日本高清色本免费现在观看| 亚洲精品福利在线观看| 久久免费精品视频| 亚洲一区动漫卡通在线播放| 一级毛片不卡片免费观看| 亚洲一区二区三区亚瑟| 国产成人无码a区在线观看视频免费| a一级爱做片免费| 亚洲毛片一级带毛片基地| 四虎免费影院4hu永久免费| 久久伊人免费视频| 亚洲精品无码久久久久秋霞 | 亚洲黄色在线视频|