前言
JDK除了提供大量的命令行之外,还提供两个强大的可视化工具Jconsole(JDK1.5提出来的)和VisualVM(JDK1.6提出来的,并且已经从JDK分离出来成为可以独立发展的开源项目)
1、jconsole
1、启动jconsole,启动之前我已经启动一个SpringBoot的web项目了
1 | healerjean$ jconsole |
2、内存监控
内存页,相当于可视化的jstat(jvm虚拟机统计信息监控),用于监控收集器管理的虚拟机内存(java堆和永久代)的变化趋势
2.1、代码测试
设置JVM参数
1 | -Xms100m -Xmx100m -XX:+UseSerialGC |
1 | package com.hlj.jvm.JvmBin.JvmJconsole; |
2.2、点击Jconsole查看内存 Eden
1、同JVM参数判断下老年代有多大内存
答:
-Xms100m -Xmx100m 可以知道Java堆区最大为100M 而上面的Eden Space最大为27328KB,所有新生代所占有的内存应该为 (27328/8 * 10 ) 堆区减去它就是老年代的内存大小了
2、执行完Systam.gc()之后老年代的柱状图依然显示峰值状态,代码需要如何调整才能让System.gc()回收掉填充到堆中的对象 Tenured Gen(老年代-养老区)看下图 需要注意的是非堆不是栈哦
答:因为在执行System.gc()之后 ,方法fillHeap并没有退出,因此 list对象在System.gc()执行时仍然处于作用域之内,将System.gc() 放到fillHeap 方法外就可以会受到全部内存
3、线程监控
这里的线程监控相当于是 jstack标签,遇到线程停顿时可以使用这个页签进行监控分析,签名讲解jstack命令的时候提到过线程长时停顿的主要原因有:等待外部资源(数据库连接,网络资源,设备资源、死循环,锁等待(活锁和死锁))
1、代码测试
这里开启两个线程,一个是,死循环while循环等待,一个是wait等待释放资源
1 | package com.hlj.jvm.JvmBin.JvmJconsole; |
1、运行main函数,观察到堆栈追踪 到readBytes等待控制台输入
2、控制台输入 你好
,出现了哪个循环等待的线程线程(会在空循环上用尽全部执行时间直到线程切换,这种等待会消耗较多的cpu资源),状态为RUNNALBE,在程序的低22行等待,22行为
1 | while (true) { |

3、再观察线程main,堆栈追踪到了59行,第二个等待控制台书输入
1 | br.readLine(); |
4、控制台输入hello,观察到又开启了另外一个线程testLockThread
,发现他的状态为warning(警告状态。在被唤醒钱不会分配执行时间) 栈堆追踪到了43行
1 | lock.wait(); |
3.2、死锁代码样例
下面的代码我只做了200个线程,目的是为了提高发送死锁的可能性,有时候,其实几个就够了的,但是概率不大,为了模拟,所以200个基本上肯定会发送死锁的,不信你就看呗
1 | package com.hlj.jvm.JvmBin.JvmJconsole; |
1、打开Jconsole 会发现出现了很多线程
2、点击检查死锁,就会出现发生死锁的的线程了
点击 201 会发现状态是block 堆栈追踪到了25行,如下代码,它的拥有者为Thread-5,同理观察其他的两个死锁线程,这样就相互卡主不存在相互释放的希望了
synchronized (Integer.valueOf(b)) {
2、VisualVM 多合一故障处理工具
2.1、软件安装与插件安装
1、安装好之后打开,安装插件,不然像个秃子一样,
2、如果发现不能下载那就是下载插件与jdk版本的问题,打开下面的链接,根据jdk版本选择合适的插件主url下载,我的是jdk1.8.0
https://visualvm.github.io/pluginscenters.html
3、复制下面这个url,放到插件设置中去,然后选择可以安装的即可
2.2、VisualVM
概述,监视,线程,MBeans的功能和Jconsole的功能差不多,主要是这里添加了很多插件,着重介绍下插件吧
2.2.1、生成,浏览器堆存储快照
在
2.2.2、Btrace(动态日志追踪) 回家再widows上操作吧,哎
它的作用是在不停止目标程序运行的前提下,通过hotspot虚拟机的Hotswap技术动态加入原来并不存在的调试代码,这项工具在实际的生产中程序操作意义很大:
出现由来:
经常遇到程序出了问题,在排查的时候,关于错误的一些必要信息,比如方法参数,返回值等在开发的时候,并没有打印到日志之中,以至于不得不停掉服务,通过调试增量来加入日志代码来解决问题。但是::::有了它在应用程序