1.jvm 모니터링 도구 소개
1.1.jconsole
JConsole의는 JVM이 실행되는 연결하기위한 JMX 기반의 GUI 도구입니다,하지만이 활성화 JVM 관리 모드를 사용해야합니다.
1.2. jconsole의 시작
은 "jconsole.exe"에 의해 자동으로 기계가 실행되는 가상 머신 프로세스의 모든을 검색합니다, JDK / bin 디렉토리에서 JConsole를 기동하는 과정을 두 번 클릭하고 모니터링을 시작합니다.
또한 "원격 접속 서버, 가상 머신의 원격 모니터링.
포트 번호에 따른 방법을 참조하십시오 추가
에서 netstat -ano | FINDSTR 8080
설명 : | FINDSTR 8080, 필터링 된 데이터가 8080을 포함하는 키워드 검색에 해당 나타냅니다
1.2.1. 개요 페이지
아래의 모니터링 인터페이스를 입력 한 후
개요 페이지는 전체 가상 머신의 개요 데이터를 실행 보여줍니다.
1.2.2. 메모리 모니터
1.2.3 라인 모니터
다음은 스레드 모니터, 당신은 쉽게 교착 상태 감지가 매우 중요합니다 수행 할 수 있습니다
1.2.4. 급 부하 모니터링
1.2.5.jvm 보고서
1.3.jvisualvm
그리고 플러그인을 많이 제공, 기능이 유사한 방법 jconsole을 제공합니다.
플러그인 카메라 GC (GC 시각화)가 여전히 사용하기 비교적 쉽고, 시각적 GC 특정 메모리 사용량을 알 수있다.
, 자바 설치 디렉토리를 열고 모드를-시작 빈 / jvisualvm.exe 응용 프로그램을 시작합니다.
2. 메모리 오버플로 전투 시뮬레이션
이 섹션에서는, JVM을 모니터링 도구 위의 실제 사례와 결합 된 JVM에 대한 깊이있는 이해가 될 것입니다!
2.1 사례 I : 메모리 전투 시뮬레이션 중
테스트 코드 :
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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个对象时,内存溢出
可视化内存信息观察:
分代回收机制理解:
https://www.cnblogs.com/newAndHui/p/11106232.html
2.2.案例二:线程等待死循环实战模拟
测试代码如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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,导出堆栈信息,查看具体原因。
2.3.案例三:线程死锁实战演示
测试代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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内存监控观察:
死锁检测:
2.3.1.死锁的构成基本条件
1、互斥条件:一份资源每次只能被一个进程或线程使用(在Java中一般体现为,一个对象锁只能被一个线程持有)
2、请求与保持条件:一个进程或线程在等待请求资源被释放时,不释放已占有资源
3、不可剥夺条件:一个进程或线程已经获得的资源不能被其他进程或线程强行剥夺
4、循环等待条件:形成一种循环等待的场景
2.4.案例四:内存快照分析
测试代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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.内存快照分析
从内存快照中可以清楚的看到产生内存溢出的原因。
内存占比列表。
还有其他的功能,大家自己点击查看。