jmc

jmc(Java Mission Control)是JDK自带的一个图形界面监控工具,监控信息非常全面。JMC打开性能日志后,主要包括一般信息、内存、代码、线程、I/O、系统、事件 功能。

image.png

JMC的最主要的特征就是JFR(Java Flight Recorder),是基于JAVA的飞行记录器,JFR的数据是一些列JVM事件的历史纪录,可以用来诊断JVM的性能和操作,收集后的数据可以使用JMC来分析。

启动JFR

在商业版本上面,JFR默认是关闭的,可以通过在启动时增加参数 -XX:+UnlockCommercialFeatures -XX:+FlightRecorder 来启动应用。启动之后,也只是开启了JFR特性,但是还没有开始进行事件记录。这就要通过GUI和命令行了。

  • 通过Java Mission Control启动JFR

    打开Java Mission Control点击对应的JVM启动即可,事件记录有两种模式(如果选择第2种模式,那么JVM会使用一个循环使用的缓存来存放事件数据):

    • 记录固定一段时间的事件(比如:1分钟)
    • 持续进行记录
  • 通过命令行启动JFR

    通过在启动的时候,增加参数:-XX:+FlightRecorderOptions=string 来启动真正地事件记录,这里的 string 可以是以下值(下列参数都可以使用jcmd命令,在JVM运行的时候进行动态调整,参考地址):

    • name=name:标识recording的名字(一个进程可以有多个recording存在,它们使用名字来进行区分)
    • defaultrecording=<ture|false>:是否启动recording,默认是false,我们要分析,必须要设置为true
    • setting=paths:包含JFR配置的文件名字
    • delay=time:启动之后,经过多长时间(比如:30s,1h)开始进行recording
    • duration=time:做多长时间的recording
    • filename=path:recordding记录到那个文件里面
    • compress=<ture|false>:是否对recording进行压缩(gzip),默认为false
    • maxage=time:在循环使用的缓存中,事件数据保存的最大时长
    • maxsize=size:事件数据缓存的最大大小(比如:1024k,1M)

常用JFR命令

  • 启动recording

    命令格式:jcmd process_id JFR.start [options_list],其中options_list就是上述的参数值。

  • dump出循环缓存中的数据

    命令格式:jcmd process_id JFR.dump [options_list],其中options_list参数的可选值如下:

    • name=name:recording的名字
    • recording=n:JFR recording的数字(一个标识recording的随机数)
    • filename=path:dump文件的保存路径
  • 查看进程中所有recording

    命令格式:jcmd process_id JFR.check [verbose],不同recording使用名字进行区分,同时JVM还为它分配一个随机数。

  • 停止recording

    命令格式:jcmd process_id JFR.stop [options_list],其中options_list参数的可选值如下:

    • name=name:要停止的recording名字
    • recording=n:要停止的recording的标识数字
    • discard=boolean:如果为true,数据被丢弃,而不是写入下面指定的文件当中
    • filename=path:写入数据的文件名称

命令启动JFR案例

  • 第一步:创建一个包含了你自己配置的JFR模板文件(template.jfc)。运行jmc, 然后Window->Flight Recording Template Manage菜单。准备好档案后,就可以导出文件,并移动到要排查问题的环境中

image.png

  • 第二步:由于JFR需要JDK的商业证书,这一步需要解锁jdk的商业特性

    [root@localhost bin]# jcmd 12234 VM.unlock_commercial_features
    12234: Commercial Features already unlocked.
    
  • 第三步:最后你就可以启动JFR,命令格式如下:

    jcmd <PID> JFR.start name=test duration=60s [settings=template.jfc] filename=output.jfr
    

    ​ 上述命令立即启动JFR并开始使用 template.jfc(在 $JAVA_HOME/jre/lib/jfr 下有 default.jfcprofile.jfc 模板)的配置收集 60s 的JVM信息,输出到 output.jfr 中。一旦记录完成之后,就可以复制.jfr文件到你的工作环境使用jmc GUI来分析。它几乎包含了排查jvm问题需要的所有信息,包括堆dump时的异常信息。使用案例如下:

    [root@localhost bin]# jcmd 12234 JFR.start name=test duration=60s filename=output.jfr
    12234: Started recording 6. The result will be written to: /root/zookeeper-3.4.12/bin/output.jfr
    [root@localhost bin]# ls -l
    -rw-r--r-- 1 root root 298585 6月  29 11:09 output.jfr
    

JFR(Java Flight Recorder)

  • Java Mission Control的最主要的特征就是Java Flight Recorder。正如它的名字所示,JFR的数据是一些列JVM事件的历史纪录,可以用来诊断JVM的性能和操作
  • JFR的基本操作就是开启哪些事件(比如:线程由于等待锁而阻塞的事件)。当开启的事件发生了,事件相关的数据会记录到内存或磁盘文件上。记录事件数据的缓存是循环使用的,只有最近发生的事件才能够从缓存中找到,之前的都因为缓存的限制被删除了。Java Mission Control能够对这些事件在界面上进行展示(从JVM的内存中读取或从事件数据文件中读取),我们可以通过这些事件来对JVM的性能进行诊断
  • 事件的类型、缓存的大小、事件数据的存储方式等等都是通过JVM参数、Java Mission Control的GUI界面、jcmd命令来控制的。JFR默认是编译进程序的,因为它的开销很小,一般来说对应用的影响小于1%。不过,如果我们增加了事件的数目、修改了记录事件的阈值,都有可能增加JFR的开销

JFR概况

​ 下面对GlassFish web服务器进行JFR记录的例子,在这个服务器上面运行着在第2章介绍的servlet。Java Mission Control加载完JFR获取的事件之后,大概是下面这个样子:

image.png

我们可以看到,通过上图可以看到:CPU使用率,Heap使用率,JVM信息,System Properties,JFR的记录情况等等。

JFR内存视图

Java Mission Control 可以看到非常多的信息,下图只显示了一个标签的内容。下图显示了JVM 的内存波动非常频繁,因为新生代经常被清除(有意思的是,head的大小并没有增长)。下面左边的面板显示了最近一段时间的垃圾回收情况,包括:GC的时长和垃圾回收的类型。如果我们点击一个事件,右边的面板会展示这个事件的具体情况,包括:垃圾垃圾回收的各个阶段及其统计信息。从面板的标签可以看到,还有很多其它信息,比如:有多少对象被清除了,花了多长时间;GC算法的配置;分配的对象信息等等。在第5章和第6章中,我们会详细介绍。

image.png

JFR 代码视图

这张图也有很多tab,可以看到各个包的使用频率和类的使用情况、异常、编译、代码缓存、类加载情况等等:

image.png

JFR事件视图

下图显示了事件的概述视图:

image.png