使用VisualVM分析性能


對於java虛擬機,像我這樣工作才兩年的會是比較陌生和神秘,但是時候,需要對JVM有一定的認識,並且能夠設置一些參數。下面是自己學習到的內容。

這里需要使用一個java自帶的一個工具,VisualVM。使用IDEA下載一個VisualVM。

一、查看程序的JVM內存

首先任務參數有不要設置,然后編寫一個程序。

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運行程序。

 

程序運行起來,但是第一次需要設置VisualVM的位置

程序運行起來后后堆的情況。

 

 上面的圖是沒有設置任何程序的事情下做的,為什么需要看堆的大小,因為堆存放對象的實例,一般都會需要設置該值,在沒有做任何設置的時候,就會看到堆的內存可能達到1G的大小。有時候需要模擬線上環境的上的Java內存大小,在IDEA中設置下一年堆的大小,這里設置堆的初始化和最大值都一樣,以避免每次垃圾回收完成后JVM重新分配內存

設置之后運行程序,堆的內存變為設置的大小,但是這個時候有可能出現異常,在我的電腦上就出現 java.lang.OutOfMemoryError: Java heap space,該異常就是設置的堆內存太小導致,但是一般情況下不會出現該情況,因為上面的程序並不需要特別大的程序,可能是我的筆記本電腦的原因。

上面知道看堆的大小,接下來可以看一下堆中存儲了什么。在程序運行的時候,需要快速點擊堆dump,然后就看到如下

雙擊某個列表之后查看其中的內容,而存儲最多的就是程序中設置的tempOOM參數,此時知道了堆中存儲最大的內容是什么,如果是其他程序,某一個字段占用特多的內存,可能就是程序出現問題了,那么就需要對那個字段進行優化。

 

 二、查看程序的線程情況

接下來運行下面的程序:

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++;
            }
        }
    
    }

 程序運行之后,查看線程標簽后直接告警出現了死鎖的線程。

上面的程序可以看到藍色部分為線程正常運行,黃色為等待。

 

三、使用VisualGC來查看年輕代,老年代的堆內存的GC情況,如果是頻繁的GC,那么可能就是內存不足,就需要增加堆內存。

上面的圖大部分的GC都是在Eden區,即對象都是朝生暮死的,並且發生了GC time收集到0條GC,那么就是該程序一直運行可以(這里程序運行時間很短,在長時間觀察,可以得到更多的信息,如果是將堆內存設置很小的時候,那么就會經常發生GC的情況)

 

JVM調優,需要變設置參數,邊進行觀察,這樣更容易理解其中緣由,可以上手試一試。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM