JVM进阶(十二):JAVA 可视化分析工具实战


一、前言

经过前几篇博文对堆内存以及垃圾收集机制的学习,相信小伙伴们已经建立了一套比较完整的理论体系!本篇博文就根据已有的理论知识,通过可视化工具来实战一番。

二、JAVA监视与管理控制台

今天要讲解的工具位于JDK/bin目录下,大家可以发现该目录下有很多可执行文件,这里都是JDK为我们提供用于分析内存的一些工具。我们重点看看jconsole.exe-JAVA监视与管理控制台

先运行以下程序:

public class Test {
	private static List<Test> list = new ArrayList<Test>();
	public static void main(String[] args) throws InterruptedException {
		for(int i=0; i<1000; i++) {
			Test test = new Test();
			list.add(test);
			Thread.sleep(50);
		}
	}
}

再双击运行可视化工具,这里会让你选择要监控的程序,我们选择刚刚运行的程序。如下图:
这里写图片描述
该页面只是一个概览页面,我们可以点进去上方导航栏的内存页,进去后我们可查看内存中各部分的使用情况图表,这里我们选择Eden区的查看。
这里写图片描述
可看到内存使用呈锯齿波状态,因为我们在循环中不断的产生新对象,而新对象又在Eden区中创建,所以内存使用会不断增加,当达到所设定的最大值后就会进行内存的回收,由于每个新生的对象都被存入到了List中,因此都不属于垃圾对象(因为处于关系网中),所以就要复制到另一个Survivor中,如果另一个Survivor区也满了,就会复制到年老区了。可查看上图右下角绿色图,在运行中会动态更新的,变化情况和刚刚说的是一样的。

当我们使用多线程的时候,会经常出现程序一直运行不会停止的情况,有可能出现死锁,有可能出现了死循环,可以通过该工具检测出来,先运行以下程序:

public class Test {
	public static void main(String[] args) throws InterruptedException {
		new Thread(new Runnable(){
			@Override
			public void run() {
				while(true){}
			}
		}).start();
	}
}

再点击导航栏上的线程进入线程查看页:
这里写图片描述
进入后页面长这个样子,看下方红色标记部分,根据我们刚刚执行的代码来看,代码开启了一个线程,作用就是执行死循环,线程的名字为默认的“Thread-0”。因为有了死循环,所以程序无法正常退出,查看堆栈跟踪,发现程序停在Test类的第14行,查看代码可发现那里是个死循环。注意:这里只是个测试例子,因此线程的名字用的是默认的,在实际环境中应为每个线程命名,在跟踪调试的过程中会大大减少工作量。

接下来我们来测试死锁的情况,运行以下代码:

public class Test {
	private static Object obj1 = new Object();
	private static Object obj2 = new Object();
	public static void main(String[] args) throws InterruptedException {
		for(int i=0; i<1000; i++) { // 循环100次,增加死锁的概率
			new Thread(new Runnable() {
				@Override
				public void run() {
					synchronized(obj1){ // 先申请obj1
						synchronized(obj2){ // 再申请obj2
							System.out.println("我是线程1");
						}
					}
				}
			}).start(); //启动线程1
			new Thread(new Runnable() {
				@Override
				public void run() {
					synchronized(obj2){ // 先申请obj2
						synchronized(obj1){ // 再申请obj1
							System.out.println("我是线程2");
						}
					}
				}
			}).start(); //启动线程2
		}
	}
}

代码中线程1先申请obj1,再申请obj2;线程2先申请obj2,再申请obj1。如果执行次数多了就会出现死锁,我们依然来看线程的监控台:
这里写图片描述
可以看出来,这么多的线程都处于等待中,不能正常退出,我们随机点一个查看,可以看到他的状态是BLOCKED。他需要的锁被线程31所持有。我们再看看31的线程,可以看到他需要的锁被线程30所持有。那么我们再看看30的线程,可以发现,30线程所需要的锁被31号线程所持有。他们互相等待,互相不释放,最终导致死锁,也导致后面那么多的线程处于BLOCKED状态。

这个可视化的工具我们就先讲这么多吧。从内存到线程,是我们在实际环境中不管是优化还是编码都会经常遇到的问题。

三、拓展阅读

  • 12
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

No Silver Bullet

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值