JConsole可视化工具介绍

本文介绍了JConsole和VisualVM两种Java应用监控工具的基本功能和使用方法。JConsole是基于JMX的可视化监视工具,可用于监控内存、线程等信息;VisualVM是一款功能强大的故障诊断工具,能够提供进程配置、性能监控、堆转储分析等功能。

JConsole 可视化工具介绍

一、 JConsole介绍

1.1 JConsole描述

Jconsole (Java Monitoring and Management Console),一种基于JMX的可视化监视、管理工具。

1.2 启动JConsole

  • 点击JDK/bin 目录下面的jconsole.exe 即可启动
  • 然后会自动自动搜索本机运行的所有虚拟机进程。
  • 选择其中一个进程可开始进行监控

JConsole连接


1.3JConsole基本介绍

JConsole 基本包括以下基本功能:概述内存线程VM概要MBean

运行下面的程序、然后使用JConsole进行监控;注意设置虚拟机参数

import java.util.ArrayList;
import java.util.List;

/**
 *  设置虚拟机参数:
 *  -Xms100M -Xms100m -XX:+UseSerialGC -XX:+PrintGCDetails
 */
public class JConsoleTool {

    static class OOMObject {
        public byte[] placeholder = new byte[64 * 1024];
    }

    public static void fillHeap(int num) throws InterruptedException {
        Thread.sleep(20000); //先运行程序,在执行监控
        List<OOMObject> list = new ArrayList<OOMObject>();
        for (int i = 0; i < num; i++) {
            // 稍作延时,令监视曲线的变化更加明显
            Thread.sleep(50);
            list.add(new OOMObject());
        }
        System.gc();
    }

    public static void main(String[] args) throws Exception {
        fillHeap(1000);
        while(true){
            //让其一直运行着
        }

    }
}

1.3.1 内存监控

内存页签相对于可视化的jstat 命令,用于监视受收集器管理的虚拟机内存。

选项描述
Eden Space 的大小27328KB
已用正在使用
已提交27328KB
最大值27328KB
copy 上的 0.120s(3收集)新生代使用赋值算法(copy),0.120s,总共三次
MarkSweepCompact上的 0.037(1收集)老年代使用标记清除整理,耗时0.037,总共一次

对应的GC日志。

[GC (Allocation Failure) [DefNew: 27277K->3392K(30720K), 0.0349173 secs] 27277K->14749K(99008K), 0.0350411 secs] [Times: user=0.03 sys=0.00, real=0.04 secs] 

[GC (Allocation Failure) [DefNew: 30691K->3378K(30720K), 0.0446635 secs] 42049K->39217K(99008K), 0.0447387 secs] [Times: user=0.03 sys=0.01, real=0.04 secs] 

[GC (Allocation Failure) [DefNew: 30679K->3372K(30720K), 0.0408609 secs] 66518K->64734K(99008K), 0.0409604 secs] [Times: user=0.02 sys=0.02, real=0.04 secs] 

[Full GC (System.gc()) [Tenured: 61362K->66352K(68288K), 0.0372192 secs] 67024K->66352K(99008K), [Metaspace: 9535K->9535K(1058816K)], 0.0373411 secs] [Times: user=0.05 sys=0.00, real=0.04 secs] 

1.3.2 线程监控

如果上面的“内存”页签相当于可视化的jstat命令的话,“线程”页签的功能相当于可视化的jstack命令,遇到线程停顿时可以使用这个页签进行监控分析。线程长时间停顿的主要原因主要有:等待外部资源(数据库连接、网络资源、设备资
源等)、死循环锁等待(活锁和死锁)


下面三个方法分别等待控制台输入、死循环演示、线程锁等待演示

/**
  * 等待控制台输入
  * @throws IOException
  */
 public static  void waitRerouceConnection () throws IOException {
     BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
     br.readLine();
 }
/**
 * 线程死循环演示
 */
 public static void createBusyThread() {
     Thread thread = new Thread(new Runnable() {
         @Override
         public void run() {
             while (true)   // 第41行
                 ;
         }
     }, "testBusyThread");
     thread.start();
 }

 /**
  * 线程锁等待演示
  */
 public static void createLockThread(final Object lock) {
     Thread thread = new Thread(new Runnable() {
         @Override
         public void run() {
             synchronized (lock) {
                 try {
                     lock.wait();
                 } catch (InterruptedException e) {
                     e.printStackTrace();
                 }
             }
         }
     }, "testLockThread");
     thread.start();
 }

(二)线程死锁演示

这段代码开了200个线程去分别计算1+2以及2+1的值,其实for循环是可省略的,两个线程也可能会导致死锁,不过那样概率太小,需要尝试运行很多次才能看到效果。一般的话,带for循环的版本最多运行2~3次就会遇到线程死锁,程序无法结束。造成死锁的原因是Integer.valueOf()方法基于减少对象创建次数和节省内存的考虑,[-128,127]之间的数字会被缓存[3],当valueOf()方法传入参数在这个范围之内,将直接返回缓存中的对象。也就是说,代码中调用了200次Integer.valueOf()方法一共就只返回了两个不同的对象。假如在某个线程的两个synchronized块之间发生了一次线程切换,那就会出现线程A等着被线程B持有的Integer.valueOf(1),线程B又等着被线程A持有的Integer.valueOf(2),结果出现大家都
跑不下去的情景。

package com.jvm;

/**
 * 线程死锁验证
 */
public class JConsoleThreadLock {

    /**
     * 线程死锁等待演示
     */
    static class SynAddRunalbe implements Runnable {
        int a, b;
        public SynAddRunalbe(int a, int b) {
            this.a = a;
            this.b = b;
        }

        @Override
        public void run() {
            synchronized (Integer.valueOf(a)) {
                synchronized (Integer.valueOf(b)) {
                    System.out.println(a + b);
                }
            }
        }
    }

    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
            new Thread(new SynAddRunalbe(1, 2)).start();
            new Thread(new SynAddRunalbe(2, 1)).start();
        }
    }


}

线程死锁

结果描述:显示了线程Thread-53在等待一个被线程Thread-66持有Integer对象,而点击线程Thread-66则显示它也在等待一个Integer对象,被线程Thread-53持有,这样两个线程就互相卡住,都不存在等到锁释放的希望了


二、 VisualVM介绍

VisualVM(All-in-One Java Troubleshooting Tool);功能最强大的运行监视和故障处理程序

2.1 功能描述

  • 显示虚拟机进程以及进程的配置环境信息jpsjinfo)。
  • 监视应用程序的CPUGC、方法区(1.7及以前),元空间(JDK1.8及以后)以及线程的信息(jstat、jstack)。
  • dump以及分析堆转储快照(jmap、jhat)。
  • 方法级的程序运行性能分析找出被调用最多、运行时间最长的方法
  • 离线程序快照:收集程序的运行时配置、线程dump、内存dump等信息建立一个快照

2.2 使用教程

如何使用,直接查看官网和本书教程即可。


参看资料

### ### JConsole 使用指南:JVM 监控与性能调优 JConsole 是 JDK 自带的一款可视化 JVM 监控工具,支持对 Java 应用的内存、线程、类加载、GC 等运行时指标进行实时监控,适用于本地和远程 JVM 分析。其基于 JMX 协议实现,能够自动搜索本机运行的 Java 进程,并通过图形界面展示关键性能数据,是轻量级、高效的监控解决方案[^4]。 #### ### 内存监控 在 JConsole 的“内存”标签页中,可以查看 JVM 堆内存和非堆内存(如元空间、直接内存)的使用情况。堆内存监控有助于识别内存泄漏或 GC 频繁触发的问题,而非堆内存则可用于分析类加载或 DirectBuffer 使用异常。通过观察内存使用曲线,可以判断是否存在内存持续增长、GC 回收效率低下等情况。若内存使用持续上升且无法回收,可能表明存在内存泄漏[^1]。 #### ### 线程监控 JConsole 提供了详细的线程监控功能,包括线程总数、活跃线程数、线程状态等。在“线程”标签页中,可以查看当前线程的堆栈信息,识别死锁、阻塞或线程池资源耗尽等问题。例如,在模拟死锁的测试代码中,多个线程因互相等待锁资源而无法继续执行,JConsole 能够检测到这些线程并提示死锁状态,有助于快速定位并发问题[^5]。 #### ### 类加载监控 在“类”标签页中,JConsole 展示了已加载类的总数、已卸载类数等信息。类加载监控对于识别元空间溢出问题(如 `OutOfMemoryError: Metaspace`)具有重要意义。若类加载数量持续增长而未被卸载,可能意味着存在类加载器泄漏或动态代理类未被回收的问题[^1]。 #### ### VM 摘要与 MBean 管理 “VM 摘要”页面提供了 JVM 的基本信息,如版本、启动参数、系统属性等,有助于快速了解运行环境。MBean 标签页则展示了所有注册的 MBean 信息,支持对 JVM 或应用自定义 MBean 的属性和操作进行管理,适用于高级监控和诊断场景[^1]。 #### ### 启动与连接配置 启动 JConsole 可通过执行 `jconsole.exe`(Windows)或 `jconsole`(Linux/macOS)命令实现,程序会自动列出本地运行的 Java 进程供选择连接。对于远程应用,需在 JVM 启动参数中添加如下配置以启用 JMX 远程监控: ```bash -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=12345 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false ``` 该配置允许 JConsole 通过指定端口连接远程 JVM,进行实时监控[^2]。 #### ### 性能调优与问题诊断 JConsole 可用于辅助性能调优,例如通过内存和线程监控识别内存泄漏、频繁 Full GC、线程阻塞等问题。结合线程快照(Thread Dump)和堆内存快照(Heap Dump),可进一步分析具体问题根源。在实际调优过程中,建议配合日志分析和代码审查,综合判断问题成因[^3]。 ---
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值