JConsole是一個基於JMX的GUI工具,用於鏈接正在運行的JVM,不過此JVM須要使用可管理的模式啓動。html
經過JDK/bin目錄下的「jconsole.exe」啓動Jconsole後,將自動搜索出本機運行的全部虛擬機進程,雙擊其中一個進程便可開始監控。java
也能夠「遠程鏈接服務器,進行遠程虛擬機的監控。服務器
補充:根據端口號查看進程jvm
netstat -ano |findstr 8080
解釋:|findstr 8080 表示過濾出包括8080的數據,至關於關鍵字查找ide
進入監控界面後以下圖工具
概述頁面顯示的是整個虛擬機主要運行數據的概覽。測試
此處的線程監控,能夠方便的進行死鎖檢測,很是重要ui
提供了和jconsole的功能相似,提供了一大堆的插件。
插件中,Visual GC(可視化GC)仍是比較好用的,可視化GC能夠看到內存的具體使用狀況。this
啓動方式,打開java安裝目錄,啓動 bin/jvisualvm.exe 應用。spa
本節將以實際案例結合上面的jvm監控工具,深刻的理解jvm!
測試代碼:
1 package com.wfd360.outofmemory; 2 3 import java.util.ArrayList; 4 5 /** 6 * VM Args: 7 * -Xms20m -Xmx20m 8 */ 9 public class TestMemory { 10 static class OOMObject { 11 public byte[] byt = new byte[1 * 1024 * 1024]; 12 } 13 14 public static void main(String[] args) throws Exception { 15 Thread.sleep(10000); 16 fillHeap(100); 17 Thread.sleep(10000); 18 } 19 20 public static void fillHeap(int num) throws Exception { 21 ArrayList<OOMObject> list = new ArrayList<OOMObject>(); 22 for (int i = 0; i < num; i++) { 23 Thread.sleep(500); 24 list.add(new OOMObject()); 25 System.out.println("num=" + i); 26 } 27 System.gc(); 28 } 29 30 31 }
測試jvm參數設置:
測試結果:
當建立第16個對象時,內存溢出
可視化內存信息觀察:
分代回收機制理解:
http://www.javashuo.com/article/p-mlkmuenu-bg.html
測試代碼以下:
1 package com.wfd360.outofmemory; 2 3 import java.io.BufferedReader; 4 import java.io.InputStreamReader; 5 6 public class TestThread { 7 /** 8 * 死循環演示 9 * 10 */ 11 public static void createBusyThread() { 12 Thread thread = new Thread(new Runnable() { 13 @Override 14 public void run() { 15 System.out.println("createBusyThread"); 16 while (true) 17 ; 18 } 19 }, "testBusyThread"); 20 thread.start(); 21 } 22 23 /** 24 * 線程鎖等待 25 * 26 */ 27 public static void createLockThread(final Object lock) { 28 Thread thread = new Thread(new Runnable() { 29 @Override 30 public void run() { 31 System.out.println("createLockThread"); 32 synchronized (lock) { 33 try { 34 lock.wait(); 35 } catch (InterruptedException e) { 36 e.printStackTrace(); 37 } 38 } 39 40 } 41 }, "testLockThread"); 42 thread.start(); 43 } 44 public static void main(String[] args) throws Exception { 45 BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 46 br.readLine(); 47 createBusyThread(); 48 br.readLine(); 49 Object object = new Object(); 50 createLockThread(object); 51 } 52 }
線程監視圖:
線程dump:
總結:經過線程可視化觀察,「testLockThread」線程一直處於等待狀態,那麼咱們就可使用dump,導出堆棧信息,查看具體緣由。
測試代碼:
1 package com.wfd360.thread; 2 3 public class DeadThread implements Runnable { 4 //控制鎖順序 5 private boolean lockFormer; 6 //對象1 7 private static Object o1 = new Object(); 8 //對象2 9 private static Object o2 = new Object(); 10 11 DeadThread(boolean lockFormer) { 12 this.lockFormer = lockFormer; 13 } 14 15 @Override 16 public void run() { 17 if (this.lockFormer) { 18 synchronized (o1) { 19 try { 20 Thread.sleep(500); 21 } catch (InterruptedException e) { 22 e.printStackTrace(); 23 } 24 synchronized (o2) { 25 System.out.println("1ok"); 26 } 27 } 28 } else { 29 synchronized (o2) { 30 try { 31 Thread.sleep(500); 32 } catch (InterruptedException e) { 33 e.printStackTrace(); 34 } 35 synchronized (o1) { 36 System.out.println("2ok"); 37 } 38 } 39 } 40 } 41 42 public static void main(String[] args) { 43 for (int i = 0; i < 200; i++) { 44 new Thread(new DeadThread(true)).start(); 45 new Thread(new DeadThread(false)).start(); 46 } 47 } 48 }
jvm內存監控觀察:
死鎖檢測:
一、互斥條件:一份資源每次只能被一個進程或線程使用(在Java中通常體現爲,一個對象鎖只能被一個線程持有)
二、請求與保持條件:一個進程或線程在等待請求資源被釋放時,不釋放已佔有資源
三、不可剝奪條件:一個進程或線程已經得到的資源不能被其餘進程或線程強行剝奪
四、循環等待條件:造成一種循環等待的場景
測試代碼:
1 package com.wfd360.outofmemory; 2 3 import java.util.ArrayList; 4 import java.util.List; 5 6 /** 7 * 演示堆內存溢出 8 * 配置jvm參數 9 * VM Args: 10 * -Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=f:/test/dump 11 * 參數-XX:+HeapDumpOnOutOfMemoryError可讓虛擬機在出現內存溢出異常時Dump出當前的內存堆轉儲快照以便過後進行分析,文件在項目中 12 */ 13 public class HeapOOM { 14 static class OOMObject { 15 public byte[] byt = new byte[1 * 1024*1024]; 16 } 17 18 public static void main(String[] args) { 19 List<OOMObject> list = new ArrayList<OOMObject>(); 20 while (true) { 21 list.add(new OOMObject()); 22 } 23 } 24 }
jvm參數配置:
測試結果:
這時生產的內存快照在 f:/test/dump 中
接下來,使用工具分析內存快照:
1.解壓 MemoryAnalyzer-1.5.0.20150527-win32.win32.x86_64.zip
百度網盤下載連接:https://pan.baidu.com/s/1NYzO2ykruGAURg2SrPJqCQ
提取碼:mtqc
2.啓動 MemoryAnalyzer.exe
3.打開剛纔生成的內存快照 f:/test/dump
4.內存快照分析
從內存快照中能夠清楚的看到產生內存溢出的緣由。
內存佔比列表。
還有其餘的功能,你們本身點擊查看。