Java-性能分析和監(jiān)控工具深入詳解
Java監(jiān)控和管理
Java監(jiān)控和管理API
Java Standard Edition(Java SE)平臺提供的監(jiān)控和管理技術(shù) - JMX(Java Management Extensions) 技術(shù)。
Java SE 中包含了用于監(jiān)控和管理的(java.lang.management)API,通過這些 API 可以實(shí)現(xiàn)應(yīng)用程序的自我監(jiān)控,此 API 主要提供了以下信息的訪問:
- 類加載相關(guān)。
- JVM 相關(guān),例如運(yùn)行時(shí)間、系統(tǒng)環(huán)境變量、用戶輸入?yún)?shù)。
- 線程相關(guān),例如線程狀態(tài),線程的統(tǒng)計(jì)信息、線程的堆棧等。
- 內(nèi)存使用情況。
- GC 情況。
- 死鎖檢測。
- 操作系統(tǒng)信息。
Java 8的java.lang.management模塊:

ClassLoadingMXBean:用于 Java 虛擬機(jī)的類加載系統(tǒng)的管理接口。
CompilationMXBean:用于 Java 虛擬機(jī)的編譯系統(tǒng)的管理接口。
GarbageCollectorMXBean:用于 Java 虛擬機(jī)的垃圾回收的管理接口。
MemoryManagerMXBean:內(nèi)存管理器的管理接口。
MemoryMXBeanJava :虛擬機(jī)的內(nèi)存系統(tǒng)的管理接口。
MemoryPoolMXBean:內(nèi)存池的管理接口。
OperatingSystemMXBean:用于操作系統(tǒng)的管理接口,Java 虛擬機(jī)在此操作系統(tǒng)上運(yùn)行。
RuntimeMXBeanJava :虛擬機(jī)的運(yùn)行時(shí)系統(tǒng)的管理接口。
ThreadMXBeanJava :虛擬機(jī)線程系統(tǒng)的管理接口。
Java虛擬機(jī)的監(jiān)控
上面說到 Java SE 中已經(jīng)內(nèi)置了開箱即用的監(jiān)控和管理功能,通過這些功能可以實(shí)現(xiàn)程序的自我監(jiān)測,Java 默認(rèn)已經(jīng)實(shí)現(xiàn)了對 Java 虛擬機(jī)相關(guān)信息的監(jiān)測。
下面通過一個(gè)簡單的示例,演示如何通過監(jiān)控管理 API 獲取系統(tǒng)信息、編譯器信息、內(nèi)存信息以及垃圾收集器信息。
public static void main(String[] args) {
showJvmInfo();
showMemoryInfo();
showSystem();
showClassLoading();
showCompilation();
showThread();
showGarbageCollector();
showMemoryManager();
showMemoryPool();
}
/**
* Java 虛擬機(jī)的運(yùn)行時(shí)系統(tǒng)
*/
public static void showJvmInfo() {
RuntimeMXBean rtMxBean = ManagementFactory.getRuntimeMXBean();
System.out.println("Java 虛擬機(jī)的運(yùn)行時(shí)系統(tǒng)(RuntimeMXBean):");
System.out.println("jvm vendor:" + rtMxBean.getVmVendor());
System.out.println("jvm name:" + rtMxBean.getVmName());
System.out.println("jvm version:" + rtMxBean.getVmVersion());
System.out.println("jvm bootClassPath:" + rtMxBean.getBootClassPath());
System.out.println("jvm start time:" + rtMxBean.getStartTime());
System.out.println("\n");
}
/**
* Java 虛擬機(jī)的內(nèi)存系統(tǒng)
*/
public static void showMemoryInfo() {
MemoryMXBean memoryMxBean = ManagementFactory.getMemoryMXBean();
MemoryUsage heap = memoryMxBean.getHeapMemoryUsage();
System.out.println("Java 虛擬機(jī)的內(nèi)存系統(tǒng)(MemoryMXBean):");
System.out.println("Heap " + heap.toString());
System.out.println(
"Heap" +
" init:" + heap.getInit() + byte2Mb(heap.getInit()) +
" used:" + byte2Mb(heap.getUsed()) +
" committed:" + byte2Mb(heap.getCommitted()) +
" max:" + byte2Mb(heap.getMax()));
System.out.println("\n");
}
private static String byte2Mb(long source) {
return "(" + source / 1024 / 1024 + "mb)";
}
/**
* Java 虛擬機(jī)在其上運(yùn)行的操作系統(tǒng)
*/
public static void showSystem() {
OperatingSystemMXBean operatingSystemMxBean = ManagementFactory.getOperatingSystemMXBean();
System.out.println("Java 虛擬機(jī)在其上運(yùn)行的操作系統(tǒng)(OperatingSystemMXBean):");
System.out.println("Architecture(操作系統(tǒng)架構(gòu)): " + operatingSystemMxBean.getArch());
System.out.println("Processors(Java虛擬機(jī)可用的處理器數(shù)): " + operatingSystemMxBean.getAvailableProcessors());
System.out.println("System name(操作系統(tǒng)名稱): " + operatingSystemMxBean.getName());
System.out.println("System version(操作系統(tǒng)版本): " + operatingSystemMxBean.getVersion());
System.out.println("Last minute load(最后一分鐘的系統(tǒng)負(fù)載平均值): " + operatingSystemMxBean.getSystemLoadAverage());
System.out.println("\n");
}
/**
* Java 虛擬機(jī)的類加載系統(tǒng)
*/
public static void showClassLoading() {
ClassLoadingMXBean classLoadingMxBean = ManagementFactory.getClassLoadingMXBean();
System.out.println("Java 虛擬機(jī)的類加載系統(tǒng)(ClassLoadingMXBean):");
System.out.println("TotalLoadedClassCount(加載的類總數(shù)): " + classLoadingMxBean.getTotalLoadedClassCount());
System.out.println("LoadedClassCount(當(dāng)前加載的類的數(shù)量)" + classLoadingMxBean.getLoadedClassCount());
System.out.println("UnloadedClassCount(卸載類的總數(shù)):" + classLoadingMxBean.getUnloadedClassCount());
System.out.println("\n");
}
/**
* Java 虛擬機(jī)的編譯系統(tǒng)
*/
public static void showCompilation() {
CompilationMXBean compilationMxBean = ManagementFactory.getCompilationMXBean();
System.out.println("Java 虛擬機(jī)的編譯系統(tǒng)(CompilationMXBean):");
System.out.println("TotalCompilationTime(編譯時(shí)間(毫秒)):" + compilationMxBean.getTotalCompilationTime());
System.out.println("name(JIT編譯器的名稱):" + compilationMxBean.getName());
System.out.println("\n");
}
/**
* Java 虛擬機(jī)的線程系統(tǒng)
*/
public static void showThread() {
ThreadMXBean threadMxBean = ManagementFactory.getThreadMXBean();
System.out.println("Java 虛擬機(jī)的線程系統(tǒng)(ThreadMXBean):");
System.out.println("ThreadCount(當(dāng)前活動線程數(shù))" + threadMxBean.getThreadCount());
System.out.println("PeakThreadCount(峰值實(shí)時(shí)線程計(jì)數(shù))" + threadMxBean.getPeakThreadCount());
System.out.println("TotalStartedThreadCount(啟動的線程總數(shù))" + threadMxBean.getTotalStartedThreadCount());
System.out.println("DaemonThreadCount(當(dāng)前活動后臺進(jìn)程線程數(shù))" + threadMxBean.getDaemonThreadCount());
System.out.println("isSynchronizerUsageSupported(虛擬機(jī)是否支持監(jiān)視可下載同步器的使用情況)" + threadMxBean.isSynchronizerUsageSupported());
System.out.println("AllThreadIds(所有活動線程ID):" + JSON.toJSONString(threadMxBean.getAllThreadIds()));
System.out.println("CurrentThreadUserTime(當(dāng)前線程在用戶模式下執(zhí)行的CPU時(shí)間(以納秒為單位))" + threadMxBean.getCurrentThreadUserTime());
for (ThreadInfo threadInfo : threadMxBean.getThreadInfo(threadMxBean.getAllThreadIds(), 1)) {
System.out.print(threadInfo.getThreadId() + threadInfo.toString());
}
System.out.println("\n");
}
/**
* Java 虛擬機(jī)中的垃圾回收器。
*/
public static void showGarbageCollector() {
List<GarbageCollectorMXBean> collectorMxBeans = ManagementFactory.getGarbageCollectorMXBeans();
System.out.println("Java 虛擬機(jī)中的垃圾回收器(GarbageCollectorMXBean):");
for (GarbageCollectorMXBean collectorMxBean : collectorMxBeans) {
System.out.println("name(垃圾收集器名稱):" + collectorMxBean.getName());
System.out.println("--CollectionCount:" + collectorMxBean.getCollectionCount());
System.out.println("--CollectionTime" + collectorMxBean.getCollectionTime());
System.out.println("\n");
}
System.out.println("\n");
}
/**
* Java 虛擬機(jī)中的內(nèi)存管理器
*/
public static void showMemoryManager() {
List<MemoryManagerMXBean> memoryManagerMxBeans = ManagementFactory.getMemoryManagerMXBeans();
System.out.println("Java 虛擬機(jī)中的內(nèi)存管理器(MemoryManagerMXBean):");
for (MemoryManagerMXBean managerMxBean : memoryManagerMxBeans) {
System.out.println("name(內(nèi)存管理器名稱):" + managerMxBean.getName());
System.out.println("--MemoryPoolNames:" + String.join(",", managerMxBean.getMemoryPoolNames()));
System.out.println("\n");
}
System.out.println("\n");
}
/**
* Java 虛擬機(jī)中的內(nèi)存池
*/
public static void showMemoryPool() {
List<MemoryPoolMXBean> memoryPoolMxBeans = ManagementFactory.getMemoryPoolMXBeans();
System.out.println("Java 虛擬機(jī)中的內(nèi)存池(MemoryPoolMXBean):");
for (MemoryPoolMXBean memoryPoolMxBean : memoryPoolMxBeans) {
System.out.println("name:" + memoryPoolMxBean.getName());
System.out.println("--CollectionUsage:" + memoryPoolMxBean.getCollectionUsage());
System.out.println("--type:" + memoryPoolMxBean.getType());
System.out.println("\n");
}
System.out.println("\n");
}
}輸出:
Java 虛擬機(jī)的運(yùn)行時(shí)系統(tǒng)(RuntimeMXBean): jvm vendor:Oracle Corporation jvm name:Java HotSpot(TM) 64-Bit Server VM jvm version:25.221-b11 jvm bootClassPath:F:\opt\Java\jdk8\jre\lib\resources.jar;F:\opt\Java\jdk8\jre\lib\rt.jar;F:\opt\Java\jdk8\jre\lib\sunrsasign.jar;F:\opt\Java\jdk8\jre\lib\jsse.jar;F:\opt\Java\jdk8\jre\lib\jce.jar;F:\opt\Java\jdk8\jre\lib\charsets.jar;F:\opt\Java\jdk8\jre\lib\jfr.jar;F:\opt\Java\jdk8\jre\classes jvm start time:1673181328952 Java 虛擬機(jī)的內(nèi)存系統(tǒng)(MemoryMXBean): Heap init = 268435456(262144K) used = 4028824(3934K) committed = 257425408(251392K) max = 3791650816(3702784K) Heap init:268435456(256mb) used:(3mb) committed:(245mb) max:(3616mb) Java 虛擬機(jī)在其上運(yùn)行的操作系統(tǒng)(OperatingSystemMXBean): Architecture(操作系統(tǒng)架構(gòu)): amd64 Processors(Java虛擬機(jī)可用的處理器數(shù)): 8 System name(操作系統(tǒng)名稱): Windows 10 System version(操作系統(tǒng)版本): 10.0 Last minute load(最后一分鐘的系統(tǒng)負(fù)載平均值): -1.0 Java 虛擬機(jī)的類加載系統(tǒng)(ClassLoadingMXBean): TotalLoadedClassCount(加載的類總數(shù)): 507 LoadedClassCount(當(dāng)前加載的類的數(shù)量)507 UnloadedClassCount(卸載類的總數(shù)):0 Java 虛擬機(jī)的編譯系統(tǒng)(CompilationMXBean): TotalCompilationTime(編譯時(shí)間(毫秒)):8 name(JIT編譯器的名稱):HotSpot 64-Bit Tiered Compilers Java 虛擬機(jī)的線程系統(tǒng)(ThreadMXBean): ThreadCount(當(dāng)前活動線程數(shù))5 PeakThreadCount(峰值實(shí)時(shí)線程計(jì)數(shù))5 TotalStartedThreadCount(啟動的線程總數(shù))5 DaemonThreadCount(當(dāng)前活動后臺進(jìn)程線程數(shù))4 isSynchronizerUsageSupported(虛擬機(jī)是否支持監(jiān)視可下載同步器的使用情況)true AllThreadIds(所有活動線程ID):[5,4,3,2,1] CurrentThreadUserTime(當(dāng)前線程在用戶模式下執(zhí)行的CPU時(shí)間(以納秒為單位))234375000 5"Attach Listener" Id=5 RUNNABLE 4"Signal Dispatcher" Id=4 RUNNABLE 3"Finalizer" Id=3 WAITING on java.lang.ref.ReferenceQueue$Lock@17c68925 at java.lang.Object.wait(Native Method) - waiting on java.lang.ref.ReferenceQueue$Lock@17c68925 2"Reference Handler" Id=2 WAITING on java.lang.ref.Reference$Lock@7e0ea639 at java.lang.Object.wait(Native Method) - waiting on java.lang.ref.Reference$Lock@7e0ea639 1"main" Id=1 RUNNABLE at sun.management.ThreadImpl.getThreadInfo1(Native Method) Java 虛擬機(jī)中的垃圾回收器(GarbageCollectorMXBean): name(垃圾收集器名稱):PS Scavenge --CollectionCount:0 --CollectionTime0 name(垃圾收集器名稱):PS MarkSweep --CollectionCount:0 --CollectionTime0 Java 虛擬機(jī)中的內(nèi)存管理器(MemoryManagerMXBean): name(內(nèi)存管理器名稱):CodeCacheManager --MemoryPoolNames:Code Cache name(內(nèi)存管理器名稱):Metaspace Manager --MemoryPoolNames:Metaspace,Compressed Class Space name(內(nèi)存管理器名稱):PS Scavenge --MemoryPoolNames:PS Eden Space,PS Survivor Space name(內(nèi)存管理器名稱):PS MarkSweep --MemoryPoolNames:PS Eden Space,PS Survivor Space,PS Old Gen Java 虛擬機(jī)中的內(nèi)存池(MemoryPoolMXBean): name:Code Cache --CollectionUsage:null --type:Non-heap memory name:Metaspace --CollectionUsage:null --type:Non-heap memory name:Compressed Class Space --CollectionUsage:null --type:Non-heap memory name:PS Eden Space --CollectionUsage:init = 67108864(65536K) used = 0(0K) committed = 0(0K) max = 1399848960(1367040K) --type:Heap memory name:PS Survivor Space --CollectionUsage:init = 11010048(10752K) used = 0(0K) committed = 0(0K) max = 11010048(10752K) --type:Heap memory name:PS Old Gen --CollectionUsage:init = 179306496(175104K) used = 0(0K) committed = 0(0K) max = 2843738112(2777088K) --type:Heap memory Disconnected from the target VM, address: '127.0.0.1:12687', transport: 'socket' Process finished with exit code 0
Java監(jiān)控和管理工具
JMX 技術(shù)中提到 JMX 不僅提供了監(jiān)控和管理的 API ,還提供了用于網(wǎng)絡(luò)遠(yuǎn)程管理的服務(wù),可以使用 JMX 相關(guān)監(jiān)控管理工具,通過網(wǎng)絡(luò)遠(yuǎn)程連接到正在運(yùn)行 Java 虛擬機(jī),監(jiān)控其運(yùn)行狀態(tài)。
JMC(Java Mission Control)
Java Mission Control使您能夠監(jiān)視和管理Java應(yīng)用程序,而不會引入通常與這些類型的工具相關(guān)聯(lián)的性能開銷。
它使用為Java虛擬機(jī)(JVM)的常規(guī)自適應(yīng)動態(tài)優(yōu)化收集的數(shù)據(jù)。
除了最小化性能開銷之外,這種方法還消除了觀察器效應(yīng)的問題,當(dāng)監(jiān)視工具改變系統(tǒng)的執(zhí)行特性時(shí)會發(fā)生這種問題。
Java Mission Control由客戶端應(yīng)用程序(JMC客戶端)和在其上運(yùn)行的許多插件組成:
- JVM Browser顯示正在運(yùn)行的Java應(yīng)用程序及其JVM。每個(gè)JVM實(shí)例都稱為JVM連接。
- JMX Console連接到正在運(yùn)行的JVM,實(shí)時(shí)收集和顯示其特征,并允許您通過Managed Beans(MBean)更改某些運(yùn)行時(shí)屬性。您還可以創(chuàng)建觸發(fā)某些事件的規(guī)則(例如,如果應(yīng)用程序的CPU使用率達(dá)到90%,則發(fā)送電子郵件)。
- Java Flight Recorder(JFR)收集并保存詳細(xì)的性能特征,以進(jìn)行歷史分析和分析。它可以用作獨(dú)立的性能監(jiān)視和分析工具,但是當(dāng)用作JMC客戶端的插件時(shí),它會在邏輯分組的表,圖表和撥號中顯示診斷信息。它使您可以選擇專注于問題所需的時(shí)間范圍和詳細(xì)程度。
- Java Mission Control插件使用Java Management Extensions(JMX)代理連接到JVM。
啟動JMC
雙擊JAvA_HOME\bin\jmc.exe 文件啟動JMC

連接遠(yuǎn)程程序添加配置:
-Dcom.sun.management.jmxremote.port=7001 -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Djava.rmi.server.hostname=your ip
JMC功能介紹
MBean瀏覽器中查看類屬性信息:

內(nèi)存欄目查看GC、各個(gè)內(nèi)存區(qū)域使用情況:

線程狀態(tài)、死鎖、堆棧信息:

診斷命令,查詢vm信息等:

JFR(Java Flight Recorder)
黑匣子是用于記錄飛機(jī)飛行和性能參數(shù)的儀器。在飛機(jī)出問題后,用于定位問題原因。JFR 就是 Java 的黑匣子。
JFR 是 Java Flight Record (Java飛行記錄) 的縮寫,是 JVM 內(nèi)置的基于事件的JDK監(jiān)控記錄框架。
這個(gè)起名就是參考了黑匣子對于飛機(jī)的作用,將Java進(jìn)程比喻成飛機(jī)飛行。
顧名思義,這個(gè)記錄主要用于問題定位和持續(xù)監(jiān)控。
如果是利用默認(rèn)配置啟動這個(gè)記錄,性能非常高效,對于業(yè)務(wù)影響很小,因?yàn)檫@個(gè)框架本來就是用來長期在線上部署的框架。
這個(gè)記錄可以輸出成二進(jìn)制文件,用戶可以指定最大記錄時(shí)間,或者最大記錄大小,供用戶在需要的時(shí)候輸出成文件進(jìn)行事后分析。
JFR在Java應(yīng)用運(yùn)行時(shí)收集對應(yīng)發(fā)生的事件,主要有三種類型的事件提供給JFR收集:
- 即時(shí)事件:一旦事件發(fā)生會立即進(jìn)行數(shù)據(jù)記錄
- 持續(xù)事件:如果持續(xù)時(shí)間超過指定閾值則進(jìn)行數(shù)據(jù)記錄
- 簡單事件:用于記錄應(yīng)用所在系統(tǒng)的活躍指標(biāo)(例如CPU,內(nèi)存等)
開啟JFR記錄
通過啟動參數(shù)配置并且啟用 JFR,也可以通過啟動參數(shù)在 JVM 進(jìn)程啟動的時(shí)候就啟動 JFR,或者是利用 jcmd 工具,動態(tài)啟用或者關(guān)閉 JFR。
JDK 8中的-XX:+FlightRecorder
java -XX:StartFlightRecording=disk=true,dumponexit=true,filename=recording.jfr,maxsize=1024m,maxage=1d,settings=profile,path-to-gc-roots=true test.Main
JConsole
Jconsole (Java Monitoring and Management Console),一種基于JMX的可視化監(jiān)視、管理工具。
JConsole 基本包括以下基本功能:概述、內(nèi)存、線程、類、VM概要、MBean。
概述

內(nèi)存

線程

可以看到線程列表、線程狀態(tài)、線程名稱、線程堆棧等信息。
類

可以看到 已加裝當(dāng)前類、已加載類總數(shù)、已卸載類總數(shù)。
VM

MXBean

JVisualVM
VisualVM(All-in-One Java Troubleshooting Tool);功能最強(qiáng)大的運(yùn)行監(jiān)視和故障處理程序。
功能描述:
- 顯示虛擬機(jī)進(jìn)程以及進(jìn)程的配置、環(huán)境信息(jps、jinfo)。
- 監(jiān)視應(yīng)用程序的CPU、GC、堆、方法區(qū)(1.7及以前),元空間(JDK1.8及以后)以及線程的信息(jstat、jstack)。
- dump以及分析堆轉(zhuǎn)儲快照(jmap、jhat)。
- 方法級的程序運(yùn)行性能分析,找出被調(diào)用最多、運(yùn)行時(shí)間最長的方法。
- 離線程序快照:收集程序的運(yùn)行時(shí)配置、線程dump、內(nèi)存dump等信息建立一個(gè)快照。






Java Management Extensions(JMX)
以上就是Java-性能分析和監(jiān)控工具深入詳解的詳細(xì)內(nèi)容,更多關(guān)于Java-性能分析&監(jiān)控工具的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
idea新建springboot項(xiàng)目pom文件報(bào)錯問題及解決
這篇文章主要介紹了idea新建springboot項(xiàng)目pom文件報(bào)錯問題及解決方案,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-04-04
通過Docker啟動Solace并在Spring?Boot通過JMS整合Solace的操作方法
本文將介紹如何在Spring中使用,雖然代碼使用的是Spring Boot,但并沒有使用相關(guān)starter,跟Spring的整合一樣,可通用,JMS是通過的消息處理框架,可以深入學(xué)習(xí)一下,不同的MQ在JMS的整合上都是類似的,感興趣的朋友跟隨小編一起看看吧2023-01-01
Java timezone設(shè)置和mybatis連接數(shù)據(jù)庫時(shí)區(qū)設(shè)置方式
這篇文章主要介紹了Java timezone設(shè)置和mybatis連接數(shù)據(jù)庫時(shí)區(qū)設(shè)置方式,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-09-09
詳解Spring Data Jpa當(dāng)屬性為Null也更新的完美解決方案
這篇文章主要介紹了詳解Spring Data Jpa當(dāng)屬性為Null也更新的完美解決方案,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2019-02-02
Java實(shí)現(xiàn)數(shù)字金額轉(zhuǎn)中文大寫金額的完整過程
本程序?qū)崿F(xiàn)將用戶輸入的整數(shù)金額(0~9999999)轉(zhuǎn)換為符合財(cái)務(wù)規(guī)范的中文大寫金額,并自動添加單位符號(如“萬”、“仟”、“佰”等),例如輸入 1234,輸出 壹仟貳佰叁拾肆元,文中通過代碼示例講解的非常詳細(xì),需要的朋友可以參考下2025-04-04
SpringBoot 集成 ShedLock 分布式鎖的示例詳解
ShedLock是一個(gè)在分布式環(huán)境中使用的定時(shí)任務(wù)框架,用于解決在分布式環(huán)境中的多個(gè)實(shí)例的相同定時(shí)任務(wù)在同一時(shí)間點(diǎn)重復(fù)執(zhí)行的問題,本文重點(diǎn)給大家介紹SpringBoot 分布式鎖ShedLock的相關(guān)知識,感興趣的朋友一起看看吧2021-08-08
java 中Collection存儲器詳解及簡單實(shí)例
這篇文章主要介紹了java 中Collection存儲器詳解及簡單實(shí)例的相關(guān)資料,需要的朋友可以參考下2017-04-04

