• 【JVM进阶之路】九:性能监控工具-可视化工具篇


    在前面已经学习了JVM性能监控的命令行工具,接下来学习JVM性能监控的命令行工具,通过可视化工具可以更直观地监控JVM性能、处理JVM相关问题。

    1、JConsole

    JConsole( Java Monitoring and Management Console),是一款基于 JMX( Java Manage-ment Extensions) 的可视化监视管理工具。

    它的功能主要是对系统进行收集和参数调整,不仅可以用在虚拟机本身的管理上,还可以用于运行于虚拟机之上的软件中。

    1.1、JConsole连接Java程序

    JConsole程序位于%JAVA_HOME%bin目录下,直接通过命令启动。

    JConsole启动和连接

    在新建连接对话框中,罗列了所有的本地Java应用程序,选择需要连接的程序即可。

    下面还有一个用于连接远程进程的文本框,输入正确的远程地址即可连接。

    如果一个程序需要使用JConsole与那成连接,则需要在启动Java程序时,加上以下参数:

    JAVA_OPTS="-Dfile.encoding=UTF-8" 
    JAVA_OPTS="$JAVA_OPTS -Dlog.dir=$LOG_PATH" 
    JAVA_OPTS="$JAVA_OPTS -Djava.rmi.server.hostname=xxx.xxx.xxx.xxx(本机IP) -Dcom.sun.management.jmxremote" 
    JAVA_OPTS="$JAVA_OPTS -Dcom.sun.management.jmxremote.port=xx" 
    JAVA_OPTS="$JAVA_OPTS -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.local.only=false"
    JAVA_OPTS="$JAVA_OPTS -Dcom.sun.management.jmxremote.ssl=false"
    

    1.2、Java程序概况

    使用JConsole连接了一个本地程序,在概述可以看到Java程序运行的概览信息,包括堆内存使用情况线程CPU使用情况四项信息的曲线图。

    JConsole概览

    1.3、内存监控

    内存的作用相当于可视化的jstat命令,用于监视被收集器管理的虚拟机内存。

    它不仅包含堆内存的整体信息,更细化到eden区、suvivior区、老年代的使用情况。

    JConsole内存监控

    为了更加清晰地查看内存地变化,运行下面一段程序,然后连接:

    /**
     * VM参数: -Xms100m -Xmx100m -XX:+UseSerialGC
     */
    public class JConcoleRAMMonitor {
    
        /***
         * 内存占位符对象,一个OOMObject大约占64KB
         */
        static class OOMObject {
            public byte[] placeholder = new byte[64 * 1024];
        }
    
        public static void fillHeap(int num) throws InterruptedException {
            List<OOMObject> list = new ArrayList<OOMObject>();
            for (int i = 0; i < num; i++) {
                // 稍作延时,令监视曲线的变化更加明显
                Thread.sleep(300);
                list.add(new OOMObject());
            }
            System.gc();
        }
    
        public static void main(String[] args) throws Exception {
            fillHeap(2000);
        }
    }
    

    这段代码的作用是以64KB/50ms的速度向Java堆中填充数据,一共填充1000次。

    观察Eden区的运行趋势,发现呈折线。观察堆内存使用,发现以稍有曲折的状态向上增长。

    Eden区内存变化状况

    执行System.gc()之后,老年代的柱状图仍然显示峰值状态,最后程序会以堆内存溢出结束,这是因为空间未能回收——List<OOMObject>list对象一直存活, fillHeap()方法仍然没有退出,如果把 System.gc()移动到fillHeap()方法外调用就可以回收掉全部内存。

    1.4、线程监控

    JConcole还可以监控线程,相当于可视化的jstack命令。如图,JConcole显示了系统内的线程数量,并在屏幕下方显示了程序中所有的线程。单击线程名称,就可以查看线程的栈信息。

    JConsole线程监控

    使用JConsole还可以快速定位死锁问题。

    这是一段会产生死锁的代码:

    public class ThreadLockDemo {
    
        /**
         * 线程死锁等待演示
         */
        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();
            }
        }
    }
    

    出现线程死锁以后,点击JConsole线程面板的检测到死锁按钮,将会看到线程的死锁信息。

    线程死锁检测

    可以看到线程Thread-199等待线程Thread-21持有的资源。

    1.5、类加载情况

    如图,类页面显示了已经装载的类数量。在详细信息栏中,还显示了已经卸载的类的数量。

    类加载情况

    1.6、虚拟机信息

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

    VM 摘要

    2、VisualVM

    VisualVM(All-in-One Java Troubleshooting Tool)是功能最强大的运行监视和故障处理程序之一,曾经在很长一段时间内是Oracle官方主力发展的虚拟机故障处理工具。

    相比一些第三方工具,VisualVM有一个很大的优点:不需要被监视的程序基于特殊Agent去运行,因此它的通用性很强,对应用程序实际性能的影响也较小,使得它可以直接应用在生产环境中。

    2.1、VisualVM安装插件

    在JDK6 Update7以后,VisualVM便作为JDK的一部分发布,它在%JAVA_HOME%bin 目录下,点击就可以启动。

    VisualVM位置

    VisualVM的精华之处在于它的插件。插件安装可以手动安装或者自动安装。

    手动安装,从地址 https://visualvm.github.io/pluginscenters.html 下载载nbm包,点击“工具->插件->已下载”菜单,然后在弹出对话框中指定nbm包路径便可完成安装。

    一般选择自动安装,点击工具-> 插件菜单,在可用插件里可以看到可安装的插件,按需安装即可。

    VisualVM安装插件

    VisualVM中概述,监视线程MBeans的功能与前面介绍的JConsole差别不大,这里就不在赘言。

    2.2、生成、浏览堆转储快照

    在VisualVM中生成堆转储快照文件有两种方式,可以执行下列任一操作:

    • 应用程序窗口中右键单击应用程序节点,然后选择堆Dump
    • 应用程序窗口中双击应用程序节点以打开应用程序标签,然后在“监视”标签中单击堆Dump

    堆Dump

    生成堆转储快照文件之后,该堆的应用程序下增加了一个以[heap-dump]开头的子节点。如果需要把堆转储快照保存或发送出去,就需要heapdump节点上右键选择“另存为”菜单,否则当VisualVM关闭时,生成的堆转储快照文件会被当作临时文件自动清理掉。要打开一个由已经存在的堆转储快照文件,通过文件菜单中的“装入”功能,选择磁盘上的文件即可。

    VisualVM生成的堆转储快照

    2.3、分析程序性能

    要开始性能分析,先选择“CPU”和“内存”按钮中的一个,然后切换到应用程序中对程序进行操作,VisualVM会记录这段时间中应用程序执行过的所有方法。

    VisualVM性能分析

    如果是进行处理器执行时间分析,将会统计每个方法的执行次数、执行耗时;

    VisualVM CPU分析

    如果是内存分析,则会统计每个方法关联的对象数以及这些对象所占的空间。

    VisualVM内存分析

    等要分析的操作执行结束后,点击“停止”按钮结束监控过程。

    2.4、BTrace动态日志跟踪

    BTrace是个很有意思的插件,它可以在不停机的情况下,通过字节码注入动态监控系统的运行情况。

    Btrace自动安装如下,到github的网络可能存在不稳定的问题,可以重试,或者手动安装

    BTrace插件安装

    在VisualVM中安装了BTrace插件后,在应用程序面板中右击要调试的程序,会出现“Trace Application…”菜单:

    image-20210407231817248

    点击将进入BTrace面板。这个面板看起来就像一个简单的Java程序开发环境:

    image-20210407231851293

    现在来尝试使用BTrace追踪正在运行的程序。

    一段简单的Java代码:产生两个1000以内的随机整数,输出这两个数字相加的结果。

    public class BTraceTest {
        public int add(int a, int b) {
            return a + b;
        }
    
        public static void main(String[] args) throws IOException {
            BTraceTest test = new BTraceTest();
            BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
            for (int i = 0; i < 10; i++) {
                reader.readLine();
                int a = (int) Math.round(Math.random() * 1000);
                int b = (int) Math.round(Math.random() * 1000);
                System.out.println(test.add(a, b));
            }
        }
    }
    

    运行程序,现在需要在不停止程序的情况下,监控程序中生成的两个随机数。在VisualVM中打开该程序的监视,在BTrace页 签填充TracingScript的内容,输入调试代码:

    /* BTrace Script Template */
    import com.sun.btrace.annotations.*;
    import static com.sun.btrace.BTraceUtils.*;
    
    @BTrace
    public class TracingScript {
    	 @OnMethod(clazz = "cn.fighter3.test.BTraceTest", 
          method = "add", 
          location = @Location(Kind.RETURN)
        )
        public static void func(@Self cn.fighter3.test.BTraceTest instance, 
            int a, int b,
            @Return int result) {
            println("调用堆栈:");
            jstack();
            println(strcat("方法参数A:", str(a)));
            println(strcat("方法参数B:", str(b)));
            println(strcat("方法结果:", str(result)));
        }
    }
    

    点击start按钮,当程序运行时将会在Output面板输出调试信息:

    image-20210407233504006

    BTrace的用途很广泛,打印调用堆栈、参数、返回值只是它最基础的使用形式,更多应用可以查看官方仓库 https://github.com/btraceio/btrace/wiki

    3、Java Mission Control

    JMV最初是JRockit虚拟机提供的一款诊断工具。在Oracle JDK7 Update 40以后,它就绑定在Oracle JDK中发布。

    JMC位置是%JAVA_HOME%/bin/jmc.exe,打开软件界面:

    JMC主要界面

    在左侧的“JVM浏览器”面板中自动显示了通过JDP协议(Java Discovery Protocol)找到的本机正在运行的HotSpot虚拟机进程。

    3.1、MBean服务器

    点击本地进程的MBean服务器

    MBean服务器

    可以看到,以飞行仪表的视图显示了Java堆使用率,CPU使用率和Live Set+Fragmentation。

    3.2、飞行记录器(Flight Recorder)

    飞行记录器是JMC提供的另一大功能,它通过记录程序在一段时间内的运行情况,将记录结果进行分析和展示,可以更进一步对系统的性能进行分析和诊断。

    要使用JFR,程序启动需要带以下参数:

    -XX:+UnlockCommercialFeatures  -XX:+FlightRecorder
    

    连接加了相关参数启动的程序,启动飞行记录,进行一分钟的性能记录:

    image-20210408000854241

    记录结束后,JMC会自动打开刚才的记录:

    image-20210408001133160

    JFR提供的数据质量通常也要比其他工具通过代理形式采样获得或者从MBean中取得的数据高得多。以垃圾搜集为例,HotSpot的MBean中一般有各个分代大小、收集次数、时间、占用率等数据(根据收集器不同有所差别),这些都属于“结果”类的信息,而JFR中还可以看到内存中这段时间分配了哪些对象、哪些在TLAB中(或外部)分配、分配速率 和压力大小如何、分配归属的线程、收集时对象分代晋升的情况等。

    4、第三方工具

    以上三个都是JDK自带的性能监控工具,除此之外还有一些第三方的性能监控工具。

    • MAT

    Java 堆内存分析工具。

    • GChisto

    GC 日志分析工具。

    • GCViewer

    GC 日志分析工具。

    • JProfiler

    商用的性能分析利器。

    • arthas

    阿里开源诊断工具。

    • async-profiler

    Java 应用性能分析工具,开源、火焰图、跨平台。

    这里只是简单罗列,就不再展开详细介绍。




    参考:

    【1】:周志明编著《深入理解Java虚拟机:JVM高级特性与最佳实践》

    【2】:《实战JAVA虚拟机 JVM故障诊断与性能优化》

    【3】:Jvm 系列(七):Jvm 调优-工具篇

    【4】:给,你们想要的排查问题的可视化工具

  • 相关阅读:
    用python写一个北京市的个税计算器
    排序算法(冒泡、选择)-python代码展示
    封装系统内置功能的函数(字符串)
    福彩习题
    打印等腰三角形
    1.冒泡排序法
    腾讯云:搭建 Node.js 环境
    python开发环境搭建
    基于 Ubuntu 搭建 FTP 文件服务
    TensorFlow — 相关 API
  • 原文地址:https://www.cnblogs.com/three-fighter/p/14636656.html
Copyright © 2020-2023  润新知