JConsole可视化工具介绍 ╰半夏微凉° 2021-11-17 23:48 371阅读 0赞 版权声明:本文为博主原创文章,欢迎转载 https://blog.csdn.net/qq_31156277/article/details/80035430 </div> <link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/ck_htmledit_views-3019150162.css"> <div id="content_views" class="markdown_views"> <!-- flowchart 箭头图标 勿删 --> <svg xmlns="http://www.w3.org/2000/svg" style="display: none;"> <path stroke-linecap="round" d="M5,0 0,2.5 5,5z" id="raphael-marker-block" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path> </svg> <h1 id="jconsole-可视化工具介绍"><a name="t0"></a>JConsole 可视化工具介绍</h1> # 一、 JConsole介绍 # ## 1.1 JConsole描述 ## > Jconsole (Java Monitoring and Management Console),一种基于JMX的可视化监视、管理工具。 ## 1.2 启动JConsole ## * 点击JDK/bin 目录下面的`jconsole.exe` 即可启动 * 然后会自动自动搜索本机运行的所有虚拟机进程。 * 选择其中一个进程可开始进行监控 ![JConsole连接][JConsole] -------------------- ## 1.3JConsole基本介绍 ## JConsole 基本包括以下基本功能:`概述`、`内存`、`线程`、`类`、`VM概要`、`MBean` 运行下面的程序、然后使用`JConsole`进行监控;注意设置虚拟机参数 import java.util.ArrayList; import java.util.List; /** * 设置虚拟机参数: * -Xms100M -Xms100m -XX:+UseSerialGC -XX:+PrintGCDetails */ public class JConsoleTool { static class OOMObject { public byte[] placeholder = new byte[64 * 1024]; } public static void fillHeap(int num) throws InterruptedException { Thread.sleep(20000); //先运行程序,在执行监控 List<OOMObject> list = new ArrayList<OOMObject>(); for (int i = 0; i < num; i++) { // 稍作延时,令监视曲线的变化更加明显 Thread.sleep(50); list.add(new OOMObject()); } System.gc(); } public static void main(String[] args) throws Exception { fillHeap(1000); while(true){ //让其一直运行着 } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 ### 1.3.1 内存监控 ### > 内存页签相对于可视化的jstat 命令,用于监视受收集器管理的虚拟机内存。 ![20180423161143839][] <table> <thead> <tr> <th align="left">选项</th> <th align="left">描述</th> </tr> </thead> <tbody> <tr> <td align="left"><code>Eden Space</code> 的大小</td> <td align="left">27328KB</td> </tr> <tr> <td align="left">已用</td> <td align="left">正在使用</td> </tr> <tr> <td align="left">已提交</td> <td align="left">27328KB</td> </tr> <tr> <td align="left">最大值</td> <td align="left">27328KB</td> </tr> <tr> <td align="left">copy 上的 0.120s(3收集)</td> <td align="left">新生代使用赋值算法(copy),0.120s,总共三次</td> </tr> <tr> <td align="left">MarkSweepCompact上的 0.037(1收集)</td> <td align="left">老年代使用标记清除整理,耗时0.037,总共一次</td> </tr> </tbody> </table> -------------------- 对应的GC日志。 [GC (Allocation Failure) [DefNew: 27277K->3392K(30720K), 0.0349173 secs] 27277K->14749K(99008K), 0.0350411 secs] [Times: user=0.03 sys=0.00, real=0.04 secs] [GC (Allocation Failure) [DefNew: 30691K->3378K(30720K), 0.0446635 secs] 42049K->39217K(99008K), 0.0447387 secs] [Times: user=0.03 sys=0.01, real=0.04 secs] [GC (Allocation Failure) [DefNew: 30679K->3372K(30720K), 0.0408609 secs] 66518K->64734K(99008K), 0.0409604 secs] [Times: user=0.02 sys=0.02, real=0.04 secs] [Full GC (System.gc()) [Tenured: 61362K->66352K(68288K), 0.0372192 secs] 67024K->66352K(99008K), [Metaspace: 9535K->9535K(1058816K)], 0.0373411 secs] [Times: user=0.05 sys=0.00, real=0.04 secs] 1 2 3 4 5 6 7 8 ### 1.3.2 线程监控 ### > 如果上面的“内存”页签相当于可视化的jstat命令的话,“线程”页签的功能相当于可视化的jstack命令,遇到线程停顿时可以使用这个页签进行监控分析。线程长时间停顿的主要原因主要有:`等待外部资源`(数据库连接、网络资源、设备资 > 源等)、`死循环`、`锁等待`(活锁和死锁) -------------------- 下面三个方法分别等待控制台输入、死循环演示、线程锁等待演示 /** * 等待控制台输入 * @throws IOException */ public static void waitRerouceConnection () throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); br.readLine(); } /** * 线程死循环演示 */ public static void createBusyThread() { Thread thread = new Thread(new Runnable() { @Override public void run() { while (true) // 第41行 ; } }, "testBusyThread"); thread.start(); } /** * 线程锁等待演示 */ public static void createLockThread(final Object lock) { Thread thread = new Thread(new Runnable() { @Override public void run() { synchronized (lock) { try { lock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } }, "testLockThread"); thread.start(); } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 -------------------- **(二)线程死锁演示** > 这段代码开了200个线程去分别计算1+2以及2+1的值,其实for循环是可省略的,两个线程也可能会导致死锁,不过那样概率太小,需要尝试运行很多次才能看到效果。一般的话,带for循环的版本最多运行2~3次就会遇到线程死锁,程序无法结束。造成死锁的原因是Integer.valueOf()方法基于减少对象创建次数和节省内存的考虑,\[-128,127\]之间的数字会被缓存\[3\],当valueOf()方法传入参数在这个范围之内,将直接返回缓存中的对象。也就是说,代码中调用了200次Integer.valueOf()方法一共就只返回了两个不同的对象。假如在某个线程的两个synchronized块之间发生了一次线程切换,那就会出现线程A等着被线程B持有的Integer.valueOf(1),线程B又等着被线程A持有的Integer.valueOf(2),结果出现大家都 > 跑不下去的情景。 package com.jvm; /** * 线程死锁验证 */ public class JConsoleThreadLock { /** * 线程死锁等待演示 */ static class SynAddRunalbe implements Runnable { int a, b; public SynAddRunalbe(int a, int b) { this.a = a; this.b = b; } @Override public void run() { synchronized (Integer.valueOf(a)) { synchronized (Integer.valueOf(b)) { System.out.println(a + b); } } } } public static void main(String[] args) { for (int i = 0; i < 100; i++) { new Thread(new SynAddRunalbe(1, 2)).start(); new Thread(new SynAddRunalbe(2, 1)).start(); } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 ![线程死锁][20180423165405892] 结果描述:显示了线程`Thread-53`在等待一个被线程`Thread-66`持有Integer对象,而点击线程`Thread-6`6则显示它也在等待一个Integer对象,被线程`Thread-53`持有,这样两个线程就互相卡住,都不存在等到锁释放的希望了 -------------------- ## 二、 VisualVM介绍 ## > VisualVM(All-in-One Java Troubleshooting Tool);功能最强大的运行监视和故障处理程序 ### 2.1 功能描述 ### * 显示虚拟机进程以及进程的`配置`、`环境信息`(`jps`、`jinfo`)。 * 监视应用程序的`CPU`、`GC`、`堆`、方法区(1.7及以前),`元空间`(JDK1.8及以后)以及`线程`的信息(jstat、jstack)。 * dump以及分析`堆转储快照`(jmap、jhat)。 * 方法级的`程序运行性能分析`,**找出被调用最多、运行时间最长的方法**。 * 离线程序快照:收集程序的运行时配置、线程dump、内存dump等信息建立一个快照 ### 2.2 使用教程 ### > 如何使用,直接查看官网和本书教程即可。 -------------------- ## 参看资料 ## * VisualVM官网地址:[帮助文档][Link 1] * [BTrace 简要介绍][BTrace] * 《深入理解java虚拟机》–周志明 [JConsole]: /images/20211116/b1ccb018317d4902895bc657fa6cbe5b.png [20180423161143839]: /images/20211116/5e4a1e71747e4fb98b668ad056879f2e.png [20180423165405892]: /images/20211116/ee47774f8e0a47e7adc0b84468c1752b.png [Link 1]: http://visualvm.github.io/documentation.html [BTrace]: https://www.jianshu.com/p/93e94b724476
还没有评论,来说两句吧...