JConsole:Java 监视与管理控制台,基于JMX的可视化监视,管理工具。
在jdk的bin目录下(如D:\Java\jdk1.8.0_131\bin),就可以找到jconsole.exe。
在运行之前,我们先写用debug执行一段程序,创建一个线程,sleep30分钟。然后,再双击启动jconsole.exe。
在如下界面中选择本地进程,笔者使用的是IDEA,这里选择第二个。
打开之后,我们可以看到概述中有四块区域的内容,堆内存使用情况,线程,类和CPU占用率。
现在,新创建一个线程,每一秒钟创建一个1M的byte数组,我们打开概述后面的内存页,再看一下。
下面笔者为大家描述一下从程序运行到崩溃都发生了什么。
首先,程序运行后,队中的内存使用量在逐渐增加,如图所示,右下角绿色的竖条,左侧第二个是新生代的Eden区,增加到24M(这里设置了程序运行的最大堆内存为90M)的时候,系统进行了一次垃圾回收。
然后,这时候会看到第三个竖条(survivor)开始增长,说明回收的内存进入到了survivor区。
再然后,当survivor区涨满之后,又进行了一次垃圾回收,最左侧的竖条,即老年代开始增长。
最后,老年代也涨满后,提示连接失败,说明程序通知运行了。为什么呢?看一下IDEA的控制台,堆内存溢出。
有意思吧!是不是验证了很多我们以前学习的知识!
当然,工具的意义不仅仅是验证,更重要的作用是为我们程序的调试提供便利。
例如,帮助我们找出程序运行缓慢的原因,下面我分别测试几种情况。
1. 等待外部资源(如数据库连接,网络资源,设备资源等),这里编写一个数据库连接并修改数据库记录的程序,然后用lock tables命令锁定表。
查看线程执行情况,我们可以看到线程一直处于等待状态,直到线程切换为止。
2. 死循环:这里我们创建一个while循环,让条件一直为true,代码如下。
我们可以看到,这个线程又很长一段时间处于执行状态,直至线程切换,这是比较消耗CPU资源的一种操作。
3. 锁等待:这里我们创建一个线程,使其一直处于等待状态,代码如下。
我们点到第三页线程页中,可以看到等待总数为1,一直处于等待当中,直到线程切换。
4. 死锁:当在线程1中先得到locka,然后再去获取锁lockb;再在线程2中得到锁lockb,再去获取锁locka,这时候线程1和线程2就变成了相互争夺,形成死锁;由于本例测试的代码来自互联网,就不贴出来了,想测试的朋友可以自行搜索。
从运行结果中,我们可以看到,在线程后面多了死锁页,里面列出了死锁的线程,并且可以看出,死锁也是持续运行了很长时间,最后线程切换才结束。
喜欢文章或想一起学习的朋友可以关注我,给我点赞,我将会持续更新,有什么疑问或文中有不当之处请给我留言,真诚地希望能与大家一起交流探讨,学习进步。