JAVA 可视化分析工具
今天要讲解的工具位于JDK目录的bin目录下,这里都是JDK为我们提供用于分析内存的一些工具。下面是jconsole.exe,JAVA监视与管理控制台。
package test04;
import java.util.ArrayList;
import java.util.List;
/**
* JConsole.exe 测试使用
* @Package test04
* @Title: Demo.java
* @Company: $
* @author BurgessLee
* @date 2018年8月29日-下午11:00:12
* @Description: $
*/
public class Demo {
private static List<Object> list = new ArrayList<>();
public static void main(String[] args) throws InterruptedException {
for(int i=1; i < 100000;i++){
list.add(new Object());
Thread.sleep(1000);
}
}
}
如图执行上述代码。然后进入jdk目录打开jconsole.exe,如下图:
点进去上方导航栏的内存页,进去后我们可查看内存中各部分的使用情况图表
如下图查看内存中Eden区的查看。
可看到内存使用呈锯齿波状态,因为我们在循环中不断的产生新对象,而新对象又在Eden区中创建,所以内存使用会不断增加,当达到所设定的最大值后就会进行内存的回收,由于每个新生的对象都被存入到了List中,因此都不属于垃圾对象(因为处于关系网中),所以就要复制到另一个Survivor中,如果另一个Survivor区也满了,就会复制到年老区了。可查看上图右下角绿色图,在运行中会动态更新的,变化情况和我刚刚说的是一样的。
使用多线程的时候,会经常出现程序一直运行不会停止的情况,有可能出现死锁,有可能出现了死循环,可以通过该工具检测出来。
执行如下的代码:
package test04;
/**
* JConsole工具测试使用2
* @Package test04
* @Title: Demo2.java
* @Company: $
* @author BurgessLee
* @date 2018年8月29日-下午11:11:10
* @Description: $
*/
public class Demo2 {
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
while(true){
System.out.println(1111);
}
}
}).start();
}
}
打开jconsole看到:
根据我们刚刚执行的代码来看,代码开启了一个线程,作用就是执行死循环,线程的名字为默认的“Thread-0”。因为有了死循环,所以程序无法正常退出,查看堆栈跟踪,发现程序停在Test类的第14行,查看代码可发现那里是个死循环。注意:这里只是个测试例子,因此线程的名字用的是默认的,在实际环境中应为每个线程命名,在跟踪调试的过程中会大大减少工作量。
接下来我们来测试死锁的情况,运行以下代码:
package test04;
/**
* JConsole测试案例3
* 测试死锁
* @Package test04
* @Title: Demo3.java
* @Company: $
* @author BurgessLee
* @date 2018年8月29日-下午11:18:09
* @Description: $
*/
public class Demo3 {
private static Object obj1 = new Object();
private static Object obj2 = new Object();
public static void main(String[] args) {
for(int i = 0; i < 100; i++){
new Thread(new Runnable() {
@Override
public void run() {
synchronized (obj1) {
synchronized (obj2) {
System.out.println("我是线程1");
}
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
synchronized (obj2) {
synchronized (obj1) {
System.out.println("我是线程2");
}
}
}
}).start();
}
}
}
可以看到:
这么多的线程都处于等待中,不能正常退出,我们随机点一个查看,可以看到他的状态是BLOCKED。他需要的锁被线程91所持有。我们再看看91的线程(就不发图了),可以看到他需要的锁被线程30所持有。那么我们再看看90的线程,可以发现,90线程所需要的锁被91号线程所持有。他们互相等待,互相不释放,最终导致死锁,也导致后面那么多的线程处于BLOCKED状态。