zoukankan      html  css  js  c++  java
  • 【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】:给,你们想要的排查问题的可视化工具

  • 相关阅读:
    ubuntu 制做samba
    《Programming WPF》翻译 第4章 前言
    《Programming WPF》翻译 第4章 3.绑定到数据列表
    《Programming WPF》翻译 第4章 4.数据源
    《Programming WPF》翻译 第5章 6.触发器
    《Programming WPF》翻译 第4章 2.数据绑定
    《Programming WPF》翻译 第4章 1.不使用数据绑定
    《Programming WPF》翻译 第5章 7.控件模板
    《Programming WPF》翻译 第5章 8.我们进行到哪里了?
    《Programming WPF》翻译 第5章 5.数据模板和样式
  • 原文地址:https://www.cnblogs.com/three-fighter/p/14636656.html
Copyright © 2011-2022 走看看