Jconsole
测试代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| import java.util.ArrayList; import java.util.List; public class HelloGC { byte[] a = new byte[1024 * 100];
public static void main(String[] args) throws InterruptedException {
List list = new ArrayList(); while (true) { list.add(new HelloGC()); Thread.sleep(100); }
} }
|

双击本地HeoolGC然后选择不安全连接

作用: 查看Java应用程序的运行概况,监视垃圾收集器管理的虚拟机内存(堆和元空间)的变化趋势,以及监控程序内的线程。
启动JConsole,在控制台输入:jconsole即可,在弹出的界面中,选择本地进程,然后进去看界面页签信息。显示的是整个虚拟机主要运行数据的概览,其中包括堆内存使用情况,线程,类,CPU使用情况四项信息的曲线图。
进来之后有很多标签的,先看默认的第一个概览
概览是对整个Jconsole功能进行一个简述其余几个是对概览的详细解释

内存
相当于命令行的jstat命令,用于监视受垃圾收集器管理的虚拟机内存(堆和元空间)的变化趋势,这不仅是包括堆内存的整体信息,更细化到伊甸区、幸存区、老年代的使用情况。同时,也包括非堆区,即元空间的使用情况,单机界面右上角的“执行GC”按钮,可以强制应用程序进行一次Full GC。

可以自己切换查看伊甸园区 老年代 非堆(元空间)的内存使用情况

线程:
相当于命令行的jstack命令,遇到线程停顿的时候可以使用它来进行监控分析。JConsole 显示了系统内的线程数量,并在屏幕下方,显示了程序中所有的线程。单击线程名称,便可以查看线程的栈信息。

类:
如图所示,显示了系统以及装载的类数量。在详细信息栏中,还显示了已卸载的类数量。

VM摘要:
在VM摘要页面,JConsole 显示了当前应用程序的运行环境。包括虚拟机类型、版本、堆信息以及虚拟机参数等。相当于jinfo命令

MBean:
MBean页面允许通过JConsole访问已经在MBean服务器注册的MBean对象。
Jconsole动态监控
上面已经讲解了Jconsole的基本使用,下面我们就通过Jconsole动态监控一下程序的运行状态。
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 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
| import java.io.IOException; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock;
public class Demo09 { public static void main(String[] args) throws IOException { System.in.read(); System.out.println("开启了死循环线程"); whileTrueThread();
System.in.read(); System.out.println("开启了等待线程"); waitThread(new Object());
System.in.read(); System.out.println("开启了死锁线程"); deadLock();
System.in.read(); }
private static void whileTrueThread() { new Thread(() -> { while (true) ; }, "whileTrueThread").start(); }
private static void waitThread(Object o) { new Thread(() -> { synchronized (o) { try { o.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } },"myWaited").start(); }
private static void deadLock() { Lock lock1 = new ReentrantLock(); Lock lock2 = new ReentrantLock(); new Thread(() -> { try { lock1.lock(); Thread.sleep(100); lock2.lock(); } catch (InterruptedException e) { e.printStackTrace(); } }, "myThread1").start(); new Thread(() -> { try { lock2.lock(); Thread.sleep(100); lock1.lock(); } catch (InterruptedException e) { e.printStackTrace(); } }, "myThread2").start(); } }
|
这是初始状态

当控制台输入一个回车 开启死循环时
CPU直接飙升到25%不下降(因为我4核4线程 所以会到25% 如果是8线程应该是12%左右,当然如果虚拟机单核的 直接97%+)

当再次回车时候开启等待线程
这是未按回车的时候(未开启等待线程)

这是按回车的时候(开启等待线程)会多了一个myWaited线程

再次会车开启死锁线程
会再次多出两个线程 状态waiting

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| 名称: myThread2 状态: java.util.concurrent.locks.ReentrantLock$NonfairSync@5b103b9b上的WAITING, 拥有者: myThread1 总阻止数: 0, 总等待数: 2
堆栈跟踪: sun.misc.Unsafe.park(Native Method) java.util.concurrent.locks.LockSupport.park(LockSupport.java:175) java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:836) java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:870) java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1199) java.util.concurrent.locks.ReentrantLock$NonfairSync.lock(ReentrantLock.java:209) java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:285) cn.itcast.un.Demo09.lambda$deadLock$3(Demo09.java:64) cn.itcast.un.Demo09$$Lambda$10/1265094477.run(Unknown Source) java.lang.Thread.run(Thread.java:748)
|
点击检测死锁时,会检测出来
