序
本文主要研究一下Java Flight Recorder的使用。java
命令
主要有5個命令,configure、check、start、dump、stop。執行順序的話,先start再dump,最後stop。macos
JFR.configure
參數 |
描述 |
值類型 |
默認值 |
globalbuffercount |
指定global buffers的數量. 修改 memorysize 參數會影響該值. |
Long |
默認值依賴 memorysize 參數. |
globalbuffersize |
指定global buffers大小, 單位bytes. 修改 memorysize 參數會影響到global buffers. |
Long |
默認值依賴 memorysize 參數. |
maxchunksize |
指定單個data chunk的最大值, 單位bytes |
Long |
12582912 |
memorysize |
指定總內存大小, 單位bytes |
Long |
10485760 |
repositorypath |
指定recordings在寫入到持久化文件以前的存儲路徑 |
String |
默認爲系統臨時目錄,Oracle Solaris以及Linux是/tmp .windows系統的話,取TMP 環境變量值 |
stackdepth |
指定stack traces的Stack depth |
Long |
64 |
thread_buffer_size |
指定每一個thread的Local buffer size, 單位bytes. 不建議修改此參數,可能會下降性能 |
Long |
8192 |
threadbufferstodisk |
是否容許thread buffers在buffer thread阻塞的時候直接寫到磁盤 |
Boolean |
false |
samplethreads |
是否開啓thread sampling |
Boolean |
true |
命令實例
jcmd 5793 JFR.configure
5793:
Current configuration:
Repository path: /private/var/folders/9r/v55wkcr91m5_g8h7lhgjzgr00000gn/T/2018_09_27_16_30_53_5793
Stack depth: 64
Global buffer count: 20
Global buffer size: 512.0 kB
Thread buffer size: 8.0 kB
Memory size: 10.0 MB
Max chunk size: 12.0 MB
Sample threads: true
JFR.start
參數 |
描述 |
值類型 |
默認值 |
delay |
指定延時多長時間纔開始記錄 |
Integer類型加s表示秒, m 表示分鐘, 或者h 表示小時 |
0s |
disk |
記錄的時候是否寫數據到磁盤 |
Boolean |
true |
dumponexit |
是否在JVM關閉時寫記錄到磁盤. 若是爲true但沒有指定filename , 則文件名爲系統生成,包含process ID, recording ID,以及 current time stamp (例如,hotspot-pid-47496-id-1-2018_01_25_19_10_41.jfr ),文件路徑爲進程啓動路徑 . |
Boolean |
false |
duration |
指定記錄時長 |
Integer類型加s表示秒, m 表示分鐘, 或者h 表示小時 |
0s (forever) |
filename |
指定中止時記錄數據的文件路徑,若是未指定,則使用進程使用目錄,例如recording.jfr `/home/user/recordings/recording.jfr`c:\recordings\recording.jfr |
String |
No default value |
maxage |
指定記錄數據在磁盤的最大存活時間,當disk參數爲true時纔有效 |
Integer類型加s表示秒, m 表示分鐘, 或者h 表示小時 |
0s (forever) |
maxsize |
指定記錄數據在磁盤的最大大小,默認單位bytes,指定m 或M 表示兆,g 或G 表示G,只有當disk參數爲true時纔有效,該值不能比maxchunksize 參數值小. |
Long |
0 (no maximum size) |
name |
指定記錄文件名,如未指定則默認生成. |
String |
默認爲系統生成. |
path-to-gc-roots |
JDK 10引入的,指定在記錄結束前要收集的GC Roots的路徑.該參數有助於排查內存泄露,可是收集比較耗時,當且僅當懷疑有內存泄露時才啓用。若是settings 參數設置爲profile , 則收集的信息包括潛在內存泄露對象的stack trace. |
Boolean |
false |
settings |
指定記錄的配置文件,若是不是JRE_HOME/lib/jfr 目錄下的要指定全路徑,要指定多個的話,用逗號分隔。默認路徑有default.jfc : 該配置開銷低,能夠用於持續運行.profile.jfc : 則提供比default更多的數據,可是開銷大一些,對性能有所影響,適合短期收集信息用 |
String |
JRE_HOME/lib/jfr/default.jfc |
命令實例
jcmd 5793 JFR.start name=demojfr dumponexit=true
5793:
Started recording 1. No limit specified, using maxsize=250MB as default.
Use jcmd 5793 JFR.dump name=demojfr filename=FILEPATH to copy recording data to file.
JFR.check
參數 |
描述 |
值類型 |
默認值 |
name |
指定文件名 |
String |
No default value |
verbose |
是否打印event settings |
Boolean |
false |
命令實例
jcmd 5793 JFR.check
5793:
Recording 1: name=demojfr maxsize=250.0MB (running)
JFR.dump
參數 |
描述 |
值類型 |
默認值 |
filename (required) |
指定dump寫入的路徑,若是未指定,則使用進程啓動的目錄,例如:recording.jfr `/home/user/recordings/recording.jfr`c:\recordings\recording.jfr |
String |
No default value |
name (required) |
指定要dump的記錄 |
String |
No default value |
path-to-gc-roots |
JDK 10引入的,指定在記錄結束前要收集的GC Roots的路徑.該參數有助於排查內存泄露,可是收集比較耗時,當且僅當懷疑有內存泄露時才啓用. |
Boolean |
false |
命令實例
jcmd 5793 JFR.dump name=demojfr filename=/tmp/demo.jfr
5793:
Dumped recording "demojfr", 480.8 kB written to:
/tmp/demo.jfr
JFR.stop
參數 |
描述 |
值類型 |
默認值 |
filename |
指定中止時數據寫入的路徑.若是沒有指定則默認爲進程啓動的目錄,例如recording.jfr `/home/user/recordings/recording.jfr`c:\recordings\recording.jfr |
String |
No default value |
name |
指定要stop的記錄的名稱 |
String |
No default value |
命令實例
jcmd 5793 JFR.stop name=demojfr
5793:
Stopped recording "demojfr".
JMC
JMC打開jfr文件實例截圖以下:
windows
讀取JFR文件
@Test
public void testReadJfr() throws IOException {
Path p = Paths.get(getClass().getClassLoader().getResource("demo.jfr").getPath());
List<RecordedEvent> events = RecordingFile.readAllEvents(p);
events.stream()
.forEach(e -> LOGGER.info("eventType:{},startTime:{},endTime:{},fields:{}",e.getEventType().getName(),e.getStartTime(),e.getEndTime(),e.getFields()));
List<String> eventNames = events.stream()
.map(e -> e.getEventType().getName())
.distinct()
.collect(Collectors.toList());
System.out.println(eventNames.toString());
}
- 直接使用jdk的api便可以解析jfr文件,讀出RecordedEvent
- eventType類型輸出以下:
[jdk.ExceptionStatistics, jdk.NativeMethodSample, jdk.ThreadSleep, jdk.JavaMonitorWait, jdk.CPULoad, jdk.JavaThreadStatistics, jdk.ClassLoadingStatistics, jdk.CompilerStatistics, jdk.ClassLoaderStatistics, jdk.ModuleExport, jdk.CodeCacheStatistics, jdk.CodeSweeperStatistics, jdk.GCConfiguration, jdk.ActiveSetting, jdk.ActiveRecording, jdk.InitialSystemProperty, jdk.InitialEnvironmentVariable, jdk.CPUInformation, jdk.CPUTimeStampCounter, jdk.ThreadAllocationStatistics, jdk.PhysicalMemory, jdk.NativeLibrary, jdk.CompilerConfiguration, jdk.CodeCacheConfiguration, jdk.CodeSweeperConfiguration, jdk.IntFlag, jdk.UnsignedIntFlag, jdk.LongFlag, jdk.UnsignedLongFlag, jdk.DoubleFlag, jdk.BooleanFlag, jdk.StringFlag, jdk.ThreadEnd, jdk.ThreadCPULoad, jdk.NetworkUtilization, jdk.ThreadStart, jdk.ThreadContextSwitchRate, jdk.GCSurvivorConfiguration, jdk.GCTLABConfiguration, jdk.GCHeapConfiguration, jdk.YoungGenerationConfiguration, jdk.SystemProcess, jdk.ThreadDump, jdk.JVMInformation, jdk.OSInformation, jdk.ModuleRequire]
除了系統定義的eventType,還能夠自定義event
自定義event
@Label("Demo Event")
@Description("Helps the programmer getting started")
public class DemoEvent extends Event {
@Label("Message")
private String message;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
DemoEvent event = new DemoEvent();
event.setMessage("hello, world!");
event.commit();
以後使用api解析jfr文件,能夠看到自定義的event,其name爲com.example.jfr.DemoEvent
能夠使用以下參數啓動-XX:StartFlightRecording=duration=120s,filename=/tmp/event.jfr,settings=default,name=DemoEventRecording
相關模塊
JDK11關於jfr的模塊有兩個,分別是jdk.jfr.jmod以及jdk.management.jfr.jmod,其具體內容以下:api
➜ jmods ../bin/jmod describe jdk.jfr.jmod
jdk.jfr@11
exports jdk.jfr
exports jdk.jfr.consumer
requires java.base mandated
qualified exports jdk.jfr.internal.management to jdk.management.jfr
contains jdk.jfr.events
contains jdk.jfr.internal
contains jdk.jfr.internal.cmd
contains jdk.jfr.internal.consumer
contains jdk.jfr.internal.dcmd
contains jdk.jfr.internal.handlers
contains jdk.jfr.internal.instrument
contains jdk.jfr.internal.jfc
contains jdk.jfr.internal.settings
contains jdk.jfr.internal.test
contains jdk.jfr.internal.types
platform macos-amd64
➜ jmods ../bin/jmod describe jdk.management.jfr.jmod
jdk.management.jfr@11
exports jdk.management.jfr
requires java.base mandated
requires java.management transitive
requires jdk.jfr
requires jdk.management
provides sun.management.spi.PlatformMBeanProvider with jdk.management.jfr.internal.FlightRecorderMXBeanProvider
contains jdk.management.jfr.internal
platform macos-amd64
小結
- Java Flight Recorder是一款優秀的java應用診斷工具,之前是商業版的特性,如今在java11當中開源出來,它導出的jfr文件能夠用Java Mission Control來分析。
- JDK11內置了相關API,能夠用來解析jfr文件,也能夠在應用程序自定義事件發佈出來
- JFR能夠採用JVM命令啓動,也能夠使用jcmd的JFR.開頭的命令在運行時操做,很是方便
doc