参考地址1
参考地址2
最近做性能测试, 无法定位到问题, 故使用内置的Java飞行记录器:Java Mission Control
.
一. 开启流程如下:
在Linux服务器上:
1. 要检查的服务的JDK要求:
- JDK是1.8u44以上. 不需要配置参数;
- JDK是1.8以下, 需要配置: -XX:+UnlockCommercialFeatures -XX:+FlightRecorder
2. 启动服务.
3. 开启飞行记录.
jcmd
说明:
- pid: 服务的进程号. 使用ps -ef | grep java 查询. (使用时去除尖括号)
- delay: 延迟开启配置. delay=10s 代表延迟10秒开启.
- duration: 指收集的日志时长. duration=15m, 代表收集15分钟的JVM信息.
- filename: 指将收集的日志存在指定的日志文件中. filename=log.jfr, 代表将收集的日志存放在log.jfr中.
二. JFR(Java Flight Recorder)
如何查看飞行记录? 下面展示如何查看飞行记录:
1. 常规选项卡
“常规”选项卡包含一些描述常规应用程序的子选项卡,第一个子选项卡是Overview,它显示了一些基本信息,如堆最大使用率,总CPU使用率和GC暂停时间,如图2-9 所示:
另外,查看一段时间内的CPU使用情况,以及应用程序使用情况和机器总数,当应用程序中出现问题时,此选项卡就变得很有用。例如,关注CPU使用率接近100%或CPU使用率过低,过长的垃圾收集暂停时间。
其他子选项卡
- JVM Information显示JVM信息。启动参数.
- “ 系统属性”,显示所有系统属性设置.
- “ 记录”显示有关特定记录的信息,例如:打开的事件。单击问号以获取有关所有选项卡和子选项卡的内置详细信息。
2. 内存选项卡
“内存”选项卡包含有垃圾收集、分配模式和对象统计信息,此选项卡有助于调试内存泄漏及调整GC。图2-10检查飞行记录 - 垃圾收集
如图2所示,堆使用的尖峰模式完全正常。在大多数应用程序中,始终分配临时对象,满足条件后,将触发垃圾收集(GC)并删除不再使用的对象。因此,堆使用量会稳定增加,直到GC被触发,然后突然下降。
Java中的大多数GC都有一些较小的垃圾收集,old GC遍历整个Java堆,而另一个GC可能会查看堆的一部分,old GC后的堆使用情况,是应用程序正在使用的内存。
启用堆统计信息生成的飞行记录,将以old GC开始和结束。在GCs列表中选择old GC,然后,选择General选项卡,以查看GC原因——堆检查启动GC。这些GC通常比其他GC要稍长一些。为了更好地处理内存泄漏,请查看第一个和最后一个old GC之后的堆。当这个值随时间增加时,可能存在内存泄漏。
“GC时间”选项卡包含有关执行GC所花费的时间,以及应用程序因GC而完全暂停的时间信息。该GC配置选项卡有GC的配置信息。有关这些选项卡的更多详细信息,请单击右上角的问号以查看内置帮助。
分配选项卡: 图3显示了内存分配选项,Java中的小对象在TLAB(线程局部区域缓冲区)中分配。TLAB是一个分配新对象的小内存区域。一旦TLAB满了,线程就会创建一个新的,所有触发新TLAB的分配都被记录下来。在TLAB之外分配较大的对象,这些对象也被记录下来。图3检查飞行记录 - 分配选项卡
要估计每个类的内存分配,在“新TLAB”选项卡中选择“分配”,然后,选择“分配”选项卡。这些分配是碰巧触发新TLAB的对象分配,char数组引发了最多的新TLABs,分配多少内存作为char数组是未知的,TLAB的大小是对char数组内存分配的估计。
图3是char数组的最大内存分配示例,单击其中一个类,以查看这些分配的堆栈跟踪。示例记录显示,44%的分配压力来自char数组,27%来自Array.copyOfRange,StringBuilder.toString依次调用Throwable.printStackTrace和StackTraceElement.toString,展开进一步以了解这些方法是如何调用的。
注意:应用程序分配的临时对象越多,应用程序必须垃圾回收的越多。“分配”选项卡可帮助找到最多的分配,并降低应用程序中的GC压力。查看TLAB选项卡外的Allocation,以查看大内存分配,这通常比New TLAB选项卡中的分配,具有更少的内存压力。
“对象统计”选项卡
“对象统计”选项卡显示实时收集最多的类。从Memory选项卡中读取Garbage Collection子选项卡以了解实时GC。图3显示了用于飞行记录的堆统计信息。启用飞行记录的堆统计信息以显示数据,底部的“Top Growers”选项卡,显示了在飞行记录期间每种对象的增加情况,特定类型对象的数量增加,通常表示存在内存泄漏,但一个小的变化是正常的,特别是,研究非标准的Java类的top growers。
代码选项卡
Code选项卡包含有关应用程序,在何处花费大部分时间的信息,在概述子选项卡显示,花费最多执行时间的包和类。这些数据来自抽样,JFR采用间隔运行的线程样本。只对实际运行代码的线程进行抽样,不会显示正在休眠、等待锁或I/O的线程。要了解应用程序时间的更多详细信息,可以查看Hot Methods子选项卡。
图5显示了采样次数最多的方法,展开这些示例,以查看调用它们的位置。如果一个HashMap.getEntry调用很多,然后展开这个节点,直到找到调用最多的方法。这是用于查找应用程序瓶颈的最佳选项卡。
“Call Tree”子选项卡:显示相同的事件,但从底部开始,例如,来自Thread.run。
Exceptions子选项卡:显示发生的异常,默认情况下,只记录错误,但在启动新记录时更改此设置以包含所有异常。
Compilations子选项卡:显示应用程序运行时实时编译的方法。
Class Loading选项卡:显示已加载的类的数量、实际加载的类和随时间推移的卸载类,此子选项卡仅包含在录制开始时,启用“Class Loading”事件时所显示的信息。
有关这些选项卡的更多详细信息,请单击右上角的问号以查看内置帮助。
线程选项卡
“线程”选项卡包含有关线程,锁争用和其他延迟的信息。
Overview 子选项卡:显示了CPU的使用情况和随着时间推移的线程数量。
Hot Threads子选项卡:显示执行大部分代码的线程,此信息与Code选项卡中的Hot Methods子选项卡使用相同的抽样数据。Contention争用标签对于找到瓶颈非常有用。
图6显示了由于同步而最等待的对象。选择一个Class以查看每个对象的等待时间的堆栈跟踪,这些暂停通常由同步方法引起。注意:默认情况下,仅记录长度超过10毫秒的同步事件,但可以在开始录制时设置此阈值。
Latencies 子选项卡:显示其他延迟源,例如,调用sleep或wait、从socket读取或等待文件I/O。
Thread Dumps 子选项卡:显示可以在记录中触发的周期性线程转储。
Lock Instances 子选项卡:显示由于同步而等待最多的对象。
有关这些选项卡的更多详细信息,单击右上角的问号以查看内置帮助。
I/O选项卡
在I/O选项卡中显示了文件读取,文件写入,socket读取,socket写入信息。这个选项卡根据应用程序的不同而有所帮助,特别是I/O操作时间很长时。
注意:认情况下,只显示大于10毫秒的事件,在创建新记录时可以修改阈值。
系统选项卡
“System”选项卡:提供有关运行应用程序的计算机的CPU,内存和操作系统的详细信息。它还显示环境变量,以及与JVM同时运行的其他进程。
事件选项卡
“Events”选项卡:显示录制中的所有事件,这是一个高级选项卡,能够以多种方式使用。有关这些选项卡的更多详细信息,单击右上角的问号以查看内置帮助。