深入理解java虛擬機器---虛擬機器工具VisualVM(十九)

來源:互聯網
上載者:User

標籤:rri   arch   ips   org   調優   準備   log4j   分享   sum   

VisualVM 是一款免費的,整合了多個 JDK 命令列工具的視覺化檢視,它能為您提供強大的分析能力,對 Java 應用程式做效能分析和調優。這些功能包括產生和分析海量資料、跟蹤記憶體流失、監控記憶體回收行程、執行記憶體和 CPU 分析,同時它還支援在 MBeans 上進行瀏覽和操作。本文主要介紹如何使用 VisualVM 進行效能分析及調優。

 

目錄:  準備工作
記憶體分析篇 記憶體堆Heap 持續保留地區PermGen CPU分析篇 線程分析篇 參考文獻

 

準備工作

自從 JDK 6 Update 7 以後已經作為 Oracle JDK 的一部分,位於 JDK 根目錄的 bin 檔案夾下,無需安裝,直接運行即可。

 

記憶體分析篇

VisualVM 通過檢測 JVM 中載入的類和對象資訊等協助我們分析記憶體使用量情況,我們可以通過 VisualVM 的監視標籤對應用程式進行記憶體分析。

1)記憶體堆Heap

首先我們來看記憶體堆Heap使用方式,我本機eclipse的進程在visualVM顯示如下:

 

隨便寫個小程式佔用記憶體大的,運行一下

程式如下:

package jvisualVM;public class JavaHeapTest {    public final static int OUTOFMEMORY = 200000000;        private String oom;    private int length;        StringBuffer tempOOM = new StringBuffer();    public JavaHeapTest(int leng) {        this.length = leng;               int i = 0;        while (i < leng) {            i++;            try {                tempOOM.append("a");            } catch (OutOfMemoryError e) {               e.printStackTrace();               break;            }        }        this.oom = tempOOM.toString();    }    public String getOom() {        return oom;    }    public int getLength() {        return length;    }    public static void main(String[] args) {        JavaHeapTest javaHeapTest = new JavaHeapTest(OUTOFMEMORY);        System.out.println(javaHeapTest.getOom().length());    }}

查看VisualVM Monitor tab, 堆記憶體變大了

 

在程式運行結束之前, 點擊Heap Dump 按鈕, 等待一會兒,得到dump結果,可以看到一些Summary資訊

點擊Classes, 發現char[]所佔用的記憶體是最大的

 

雙擊它,得到如下Instances結果

 Instances是按Size由大到小排列的

第一個就是最大的, 展開Field地區的 values

StringBuffer類型的 全域變數 tempOOM 佔用記憶體特別大, 注意局部變數是無法通過 堆dump來得到分析結果的。

另外,對於“堆 dump”來說,在遠程監控jvm的時候,VisualVM是沒有這個功能的,只有本地監控的時候才有。

 

 ###轉載註明出處:http://www.cnblogs.com/wade-xu/p/4369094.html 

 

2)持續保留地區PermGen

其次來看下持續保留地區PermGen使用方式

運行一段類載入的程式,代碼如下:

package jvisualVM;import java.io.File;import java.lang.reflect.Method;import java.net.MalformedURLException;import java.net.URL;import java.net.URLClassLoader;import java.util.ArrayList;import java.util.List;public class TestPermGen {        private static List<Object> insList = new ArrayList<Object>();    public static void main(String[] args) throws Exception {        permLeak();    }    private static void permLeak() throws Exception {        for (int i = 0; i < 1000; i++) {            URL[] urls = getURLS();            URLClassLoader urlClassloader = new URLClassLoader(urls, null);            Class<?> logfClass = Class.forName("org.apache.commons.logging.LogFactory", true,urlClassloader);            Method getLog = logfClass.getMethod("getLog", String.class);            Object result = getLog.invoke(logfClass, "TestPermGen");            insList.add(result);            System.out.println(i + ": " + result);        }    }    private static URL[] getURLS() throws MalformedURLException {        File libDir = new File("C:/Users/wadexu/.m2/repository/commons-logging/commons-logging/1.1.1");        File[] subFiles = libDir.listFiles();        int count = subFiles.length;        URL[] urls = new URL[count];        for (int i = 0; i < count; i++) {            urls[i] = subFiles[i].toURI().toURL();        }        return urls;    }    }

一個類型裝載之後會建立一個對應的java.lang.Class執行個體,這個執行個體本身和普通對象執行個體一樣儲存於堆中,我覺得之所以說是這是一種特殊的執行個體,某種程度上是因為其充當了訪問PermGen地區中類型資訊的代理者。

 

運行一段時間後拋OutOfMemoryError了, VisualVM監控結果如下:

 

結論:PermGen地區分配的堆空間過小,我們可以通過設定-XX: PermSize參數和-XX:MaxPermSize參數來解決。

關於PermGen OOM深入分析請參考這篇文章

關於Perform GC, 請參考這篇文章

這部分知識還是比較深入的,有空還要繼續研究。

 

###轉載註明出處:http://www.cnblogs.com/wade-xu/p/4369094.html 

 

CPU分析篇

CPU 效能分析的主要目的是統計函數的調用情況及執行時間,或者更簡單的情況就是統計應用程式的 CPU 使用方式。

沒有程式運行時的 CPU 使用方式如:

 

運行一段 佔用CPU 的小程式,代碼如下

package jvisualVM;public class MemoryCpuTest {    public static void main(String[] args) throws InterruptedException {        cpuFix();    }    /**     * cpu 運行固定百分比     *      * @throws InterruptedException     */    public static void cpuFix() throws InterruptedException {        // 80%的佔有率        int busyTime = 8;        // 20%的佔有率        int idelTime = 2;        // 開始時間        long startTime = 0;                while (true) {            // 開始時間            startTime = System.currentTimeMillis();                        /*             * 已耗用時間             */            while (System.currentTimeMillis() - startTime < busyTime) {                ;            }                        // 休息時間            Thread.sleep(idelTime);        }    }}

查看監視頁面 Monitor tab

 

過高的 CPU 使用率可能是由於我們的項目中存在低效的代碼;

在我們對程式施壓的時候,過低的 CPU 使用率也有可能是程式的問題。

 

點擊取樣器Sampler, 點擊“CPU”按鈕, 啟動CPU效能分析會話,VisualVM 會檢測應用程式所有的被調用的方法,

在CPU samples tab 下可以看到我們的方法cpufix() 的自用時間最長, 如:

切換到Thread CPU Time 頁面下,我們的 main 函數這個進程 佔用CPU時間最長, 如:

 ###轉載註明出處:http://www.cnblogs.com/wade-xu/p/4369094.html 

 

線程分析篇

Java 語言能夠很好的實現多線程應用程式。當我們對一個多線程應用程式進行調試或者開發後期做效能調優的時候,往往需要瞭解當前程式中所有線程的運行狀態,是否有死結、熱鎖等情況的發生,從而分析系統可能存在的問題。

在 VisualVM 的監視標籤內,我們可以查看當前應用程式中所有活動線程(Live threads)和守護線程(Daemon threads)的數量等即時資訊。

 

運行一段小程式,代碼如下:

package jvisualVM;public class MyThread extends Thread{        public static void main(String[] args) {                MyThread mt1 = new MyThread("Thread a");        MyThread mt2 = new MyThread("Thread b");                mt1.setName("My-Thread-1 ");        mt2.setName("My-Thread-2 ");                mt1.start();        mt2.start();    }        public MyThread(String name) {    }    public void run() {                while (true) {                    }    }    }

 

Live threads 從11增加兩個 變成13了

Daemon threads從8增加兩個 變成10了 

 

VisualVM 的線程標籤提供了三種視圖,預設會以時間軸的方式展現, 如:

可以看到兩個我們run的程式裡啟的線程:My-Thread-1 和 My-Thread-2

 

另外還有兩種視圖分別是表視圖和詳細資料檢視, 這裡看一下每個Thread的詳細視圖:

 ###轉載註明出處:http://www.cnblogs.com/wade-xu/p/4369094.html 

 

再來一段死結的程式,看VisualVM 能否分析出來

package jvisualVM;public class DeadLock {    public static void main(String[] args) {        Resource r1 = new Resource();        Resource r0 = new Resource();        Thread myTh1 = new LockThread1(r1, r0);        Thread myTh0 = new LockThread0(r1, r0);        myTh1.setName("DeadLock-1 ");        myTh0.setName("DeadLock-0 ");        myTh1.start();        myTh0.start();    }}    class Resource {        private int i;            public int getI() {            return i;        }            public void setI(int i) {            this.i = i;        }            }    class LockThread1 extends Thread {        private Resource r1, r2;            public LockThread1(Resource r1, Resource r2) {            this.r1 = r1;            this.r2 = r2;        }            @Override        public void run() {            int j = 0;            while (true) {                synchronized (r1) {                    System.out.println("The first thread got r1‘s lock " + j);                    synchronized (r2) {                        System.out.println("The first thread got r2‘s lock  " + j);                    }                }                j++;            }        }        }    class LockThread0 extends Thread {        private Resource r1, r2;            public LockThread0(Resource r1, Resource r2) {            this.r1 = r1;            this.r2 = r2;        }            @Override        public void run() {            int j = 0;            while (true) {                synchronized (r2) {                    System.out.println("The second thread got r2‘s lock  " + j);                    synchronized (r1) {                        System.out.println("The second thread got r1‘s lock" + j);                    }                }                j++;            }        }        }

 

開啟VisualVM檢測到的JVM進程,我們可以看到這個tab在閃,VisualVM已經檢測到我這個package下面的DeadLock類出錯了

切換到Thread tab, 可以看到死結了, Deadlock detected!

另外可以點擊Thread Dump 線程轉儲,進一步分析,在這裡就不贅述了,有興趣的讀者可以自行實驗。

 

 

參考文獻:

http://www.ibm.com/developerworks/cn/java/j-lo-visualvm/

轉自:http://www.cnblogs.com/wade-xu/p/4369094.html 

 

  

深入理解java虛擬機器---虛擬機器工具VisualVM(十九)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.