19.1. 工具概述
使用上一章命令行工具或組合能幫您獲取目標Java應用性能相關的基礎信息,但它們存在下列局限:
- 1.無法獲取方法級別的分析數據,如方法間的調用關系、各方法的調用次數和調用時間等(這對定位應用性能瓶頸至關重要)。
- 2.要求用戶登錄到目標 Java 應用所在的宿主機上,使用起來不是很方便。
- 3.分析數據通過終端輸出,結果展示不夠直觀。
為此,JDK提供了一些內存泄漏的分析工具,如jconsole,jvisualvm等,用于輔助開發人員定位問題,但是這些工具很多時候并不足以滿足快速定位的需求。所以這里我們介紹的工具相對多一些、豐富一些。
JDK自帶的工具
- jconsole:JDK自帶的可視化監控工具。查看Java應用程序的運行概況、監控堆信息、永久區(或元空間)使用情況、類加載情況等
- Visual VM:Visual VM是一個工具,它提供了一個可視界面,用于查看Java虛擬機上運行的基于Java技術的應用程序的詳細信息。
- JMC:Java Mission Control,內置Java Flight Recorder。能夠以極低的性能開銷收集Java虛擬機的性能數據。
第三方工具
- MAT:MAT(Memory Analyzer Tool)是基于Eclipse的內存分析工具,是一個快速、功能豐富的Java heap分析工具,它可以幫助我們查找內存泄漏和減少內存消耗
- JProfiler:商業軟件,需要付費。功能強大。
19.2. JConsole
jconsole:從Java5開始,在JDK中自帶的java監控和管理控制臺。用于對JVM中內存、線程和類等的監控,是一個基于JMX(java management extensions)的GUI性能監控工具。
官方地址:https://docs.oracle.com/javase/7/docs/technotes/guides/management/jconsole.html
19.3. Visual VM
Visual VM是一個功能強大的多合一故障診斷和性能監控的可視化工具。它集成了多個JDK命令行工具,使用Visual VM可用于顯示虛擬機進程及進程的配置和環境信息(jps,jinfo),監視應用程序的CPU、GC、堆、方法區及線程的信息(jstat、jstack)等,甚至代替JConsole。在JDK 6 Update 7以后,Visual VM便作為JDK的一部分發布(VisualVM 在JDK/bin目錄下)即:它完全免費。
主要功能:
- 1.生成/讀取堆內存/線程快照
- 2.查看JVM參數和系統屬性
- 3.查看運行中的虛擬機進程
- 4.程序資源的實時監控
- 5.JMX代理連接、遠程環境監控、CPU分析和內存分析
官方地址:https://visualvm.github.io/index.html
19.4. Eclipse MAT
MAT(Memory Analyzer Tool)工具是一款功能強大的Java堆內存分析器。可以用于查找內存泄漏以及查看內存消耗情況。MAT是基于Eclipse開發的,不僅可以單獨使用,還可以作為插件的形式嵌入在Eclipse中使用。是一款免費的性能分析工具,使用起來非常方便。
MAT可以分析heap dump文件。在進行內存分析時,只要獲得了反映當前設備內存映像的hprof文件,通過MAT打開就可以直觀地看到當前的內存信息。一般說來,這些內存信息包含:
- 所有的對象信息,包括對象實例、成員變量、存儲于棧中的基本類型值和存儲于堆中的其他對象的引用值。
- 所有的類信息,包括classloader、類名稱、父類、靜態變量等
- GCRoot到所有的這些對象的引用路徑
- 線程信息,包括線程的調用棧及此線程的線程局部變量(TLS)
MAT 不是一個萬能工具,它并不能處理所有類型的堆存儲文件。但是比較主流的廠家和格式,例如Sun,HP,SAP 所采用的 HPROF 二進制堆存儲文件,以及 IBM的 PHD 堆存儲文件等都能被很好的解析。
最吸引人的還是能夠快速為開發人員生成內存泄漏報表,方便定位問題和分析問題。雖然MAT有如此強大的功能,但是內存分析也沒有簡單到一鍵完成的程度,很多內存問題還是需要我們從MAT展現給我們的信息當中通過經驗和直覺來判斷才能發現。
官方地址: https://www.eclipse.org/mat/downloads.php
19.4.5、mac安裝MAT
- 下載安裝之后配置jdk,修改:MemoryAnalyzer.ini
vim /Applications/mat.app/Contents/Eclipse/MemoryAnalyzer.ini
- 增加了第一行:設置Java
- windows下使用的不是java,是javaw
-vm
/Users/wandaren/develop/jdk/jdk-17.0.4.1+1/Contents/Home/bin/java
-startup
../Eclipse/plugins/org.eclipse.equinox.launcher_1.6.400.v20210924-0641.jar
--launcher.library
../Eclipse/plugins/org.eclipse.equinox.launcher.cocoa.macosx.x86_64_1.2.400.v20211117-0650
-vmargs
-Xmx1024m
-Dorg.eclipse.swt.internal.carbon.smallFonts
-XstartOnFirstThread
19.5. JProfiler
在運行Java的時候有時候想測試運行時占用內存情況,這時候就需要使用測試工具查看了。在eclipse里面有 Eclipse Memory Analyzer tool(MAT)插件可以測試,而在IDEA中也有這么一個插件,就是JProfiler。JProfiler 是由 ej-technologies 公司開發的一款 Java 應用性能診斷工具。功能強大,但是收費。
特點:
- 使用方便、界面操作友好(簡單且強大)
- 對被分析的應用影響小(提供模板)
- CPU,Thread,Memory分析功能尤其強大
- 支持對jdbc,noSql,jsp,servlet,socket等進行分析
- 支持多種模式(離線,在線)的分析
- 支持監控本地、遠程的JVM
- 跨平臺,擁有多種操作系統的安裝版本
主要功能:
- 1-方法調用:對方法調用的分析可以幫助您了解應用程序正在做什么,并找到提高其性能的方法
- 2-內存分配:通過分析堆上對象、引用鏈和垃圾收集能幫您修復內存泄露問題,優化內存使用
- 3-線程和鎖:JProfiler提供多種針對線程和鎖的分析視圖助您發現多線程問題
- 4-高級子系統:許多性能問題都發生在更高的語義級別上。例如,對于JDBC調用,您可能希望找出執行最慢的SQL語句。JProfiler支持對這些子系統進行集成分析
官網地址:https://www.ej-technologies.com/products/jprofiler/overview.html
數據采集方式:
JProfier數據采集方式分為兩種:Sampling(樣本采集)和Instrumentation(重構模式)
Instrumentation:這是JProfiler全功能模式。在class加載之前,JProfier把相關功能代碼寫入到需要分析的class的bytecode中,對正在運行的jvm有一定影響。
- 優點:功能強大。在此設置中,調用堆棧信息是準確的。
- 缺點:若要分析的class較多,則對應用的性能影響較大,CPU開銷可能很高(取決于Filter的控制)。因此使用此模式一般配合Filter使用,只對特定的類或包進行分析
Sampling:類似于樣本統計,每隔一定時間(5ms)將每個線程棧中方法棧中的信息統計出來。
- 優點:對CPU的開銷非常低,對應用影響小(即使你不配置任何Filter)
- 缺點:一些數據/特性不能提供(例如:方法的調用次數、執行時間)
注:JProfiler本身沒有指出數據的采集類型,這里的采集類型是針對方法調用的采集類型。因為JProfiler的絕大多數核心功能都依賴方法調用采集的數據,所以可以直接認為是JProfiler的數據采集類型。
遙感監測 Telemetries
內存視圖 Live Memory
Live memory 內存剖析:class/class instance的相關信息。例如對象的個數,大小,對象創建的方法執行棧,對象創建的熱點。
- 所有對象 All Objects:顯示所有加載的類的列表和在堆上分配的實例數。只有Java 1.5(JVMTI)才會顯示此視圖。
- 記錄對象 Record Objects:查看特定時間段對象的分配,并記錄分配的調用堆棧。
- 分配訪問樹 Allocation Call Tree:顯示一棵請求樹或者方法、類、包或對已選擇類有帶注釋的分配信息的J2EE組件。
- 分配熱點 Allocation Hot Spots:顯示一個列表,包括方法、類、包或分配已選類的J2EE組件。你可以標注當前值并且顯示差異值。對于每個熱點都可以顯示它的跟蹤記錄樹。
- 類追蹤器 Class Tracker:類跟蹤視圖可以包含任意數量的圖表,顯示選定的類和包的實例與時間。
堆遍歷 heap walker
cpu視圖 cpu views
JProfiler 提供不同的方法來記錄訪問樹以優化性能和細節。線程或者線程組以及線程狀況可以被所有的視圖選擇。所有的視圖都可以聚集到方法、類、包或J2EE組件等不同層上。
- 訪問樹 Call Tree:顯示一個積累的自頂向下的樹,樹中包含所有在JVM中已記錄的訪問隊列。JDBC,JMS和JNDI服務請求都被注釋在請求樹中。請求樹可以根據Servlet和JSP對URL的不同需要進行拆分。
- 熱點 Hot Spots:顯示消耗時間最多的方法的列表。對每個熱點都能夠顯示回溯樹。該熱點可以按照方法請求,JDBC,JMS和JNDI服務請求以及按照URL請求來進行計算。
- 訪問圖 Call Graph:顯示一個從已選方法、類、包或J2EE組件開始的訪問隊列的圖。
- 方法統計 Method Statistis:顯示一段時間內記錄的方法的調用時間細節。
線程視圖 threads
JProfiler通過對線程歷史的監控判斷其運行狀態,并監控是否有線程阻塞產生,還能將一個線程所管理的方法以樹狀形式呈現。對線程剖析。
- 線程歷史 Thread History:顯示一個與線程活動和線程狀態在一起的活動時間表。
- 線程監控 Thread Monitor:顯示一個列表,包括所有的活動線程以及它們目前的活動狀況。
- 線程轉儲 Thread Dumps:顯示所有線程的堆棧跟蹤。
線程分析主要關心三個方面:
- 1.web容器的線程最大數。比如:Tomcat的線程容量應該略大于最大并發數。
- 2.線程阻塞
- 3.線程死鎖
監控和鎖 Monitors &Locks
所有線程持有鎖的情況以及鎖的信息。觀察JVM的內部線程并查看狀態:
- 死鎖探測圖表 Current Locking Graph:顯示JVM中的當前死鎖圖表。
- 目前使用的監測器 Current Monitors:顯示目前使用的監測器并且包括它們的關聯線程。
- 鎖定歷史圖表 Locking History Graph:顯示記錄在JVM中的鎖定歷史。
- 歷史檢測記錄 Monitor History:顯示重大的等待事件和阻塞事件的歷史記錄。
- 監控器使用統計 Monitor Usage Statistics:顯示分組監測,線程和監測類的統計監測數據
19.6. Arthas
上述工具都必須在服務端項目進程中配置相關的監控參數,然后工具通過遠程連接到項目進程,獲取相關的數據。這樣就會帶來一些不便,比如線上環境的網絡是隔離的,本地的監控工具根本連不上線上環境。并且類似于Jprofiler這樣的商業工具,是需要付費的。
那么有沒有一款工具不需要遠程連接,也不需要配置監控參數,同時也提供了豐富的性能監控數據呢?
阿里巴巴開源的性能分析神器Arthas應運而生。
Arthas是Alibaba開源的Java診斷工具,深受開發者喜愛。在線排查問題,無需重啟;動態跟蹤Java代碼;實時監控JVM狀態。Arthas 支持JDK 6+,支持Linux/Mac/Windows,采用命令行交互模式,同時提供豐富的 Tab 自動補全功能,進一步方便進行問題的定位和診斷。當你遇到以下類似問題而束手無策時,Arthas可以幫助你解決:
- 這個類從哪個 jar 包加載的?為什么會報各種類相關的 Exception?
- 我改的代碼為什么沒有執行到?難道是我沒 commit?分支搞錯了?
- 遇到問題無法在線上 debug,難道只能通過加日志再重新發布嗎?
- 線上遇到某個用戶的數據處理有問題,但線上同樣無法 debug,線下無法重現!
- 是否有一個全局視角來查看系統的運行狀況?
- 有什么辦法可以監控到JVM的實時運行狀態?
- 怎么快速定位應用的熱點,生成火焰圖?
官方地址:https://arthas.aliyun.com/doc/quick-start.html
安裝方式:如果速度較慢,可以嘗試國內的碼云Gitee下載。
wget https://io/arthas/arthas-boot.jar
wget https://arthas/gitee/io/arthas-boot.jar
Arthas只是一個java程序,所以可以直接用java -jar運行。
除了在命令行查看外,Arthas目前還支持 Web Console。在成功啟動連接進程之后就已經自動啟動,可以直接訪問 http://127.0.0.1:8563/ 訪問,頁面上的操作模式和控制臺完全一樣。
基礎指令
quit/exit 退出當前 Arthas客戶端,其他 Arthas喜戶端不受影響
stop/shutdown 關閉 Arthas服務端,所有 Arthas客戶端全部退出
help 查看命令幫助信息
cat 打印文件內容,和linux里的cat命令類似
echo 打印參數,和linux里的echo命令類似
grep 匹配查找,和linux里的gep命令類似
tee 復制標隹輸入到標準輸出和指定的文件,和linux里的tee命令類似
pwd 返回當前的工作目錄,和linux命令類似
cls 清空當前屏幕區域
session 查看當前會話的信息
reset 重置增強類,將被 Arthas增強過的類全部還原, Arthas服務端關閉時會重置所有增強過的類
version 輸出當前目標Java進程所加載的 Arthas版本號
history 打印命令歷史
keymap Arthas快捷鍵列表及自定義快捷鍵
jvm相關
dashboard 當前系統的實時數據面板
thread 查看當前JVM的線程堆棧信息
jvm 查看當前JVM的信息
sysprop 查看和修改JVM的系統屬性
sysem 查看JVM的環境變量
vmoption 查看和修改JVM里診斷相關的option
perfcounter 查看當前JVM的 Perf Counter信息
logger 查看和修改logger
getstatic 查看類的靜態屬性
ognl 執行ognl表達式
mbean 查看 Mbean的信息
heapdump dump java heap,類似jmap命令的 heap dump功能
class/classloader相關
sc 查看JVM已加載的類信息-d 輸出當前類的詳細信息,包括這個類所加載的原始文件來源、類的聲明、加載的Classloader等詳細信息。如果一個類被多個Classloader所加載,則會出現多次-E 開啟正則表達式匹配,默認為通配符匹配-f 輸出當前類的成員變量信息(需要配合參數-d一起使用)-X 指定輸出靜態變量時屬性的遍歷深度,默認為0,即直接使用toString輸出
sm 查看已加載類的方法信息-d 展示每個方法的詳細信息-E 開啟正則表達式匹配,默認為通配符匹配
jad 反編譯指定已加載類的源碼
mc 內存編譯器,內存編譯.java文件為.class文件
retransform 加載外部的.class文件, retransform到JVM里
redefine 加載外部的.class文件,redefine到JVM里
dump dump已加載類的byte code到特定目錄
classloader 查看classloader的繼承樹,urts,類加載信息,使用classloader去getResource-t 查看classloader的繼承樹-l 按類加載實例查看統計信息-c 用classloader對應的hashcode來查看對應的 Jar urls
monitor/watch/trace相關
monitor 方法執行監控,調用次數、執行時間、失敗率-c 統計周期,默認值為120秒
watch 方法執行觀測,能觀察到的范圍為:返回值、拋出異常、入參,通過編寫groovy表達式進行對應變量的查看-b 在方法調用之前觀察(默認關閉)-e 在方法異常之后觀察(默認關閉)-s 在方法返回之后觀察(默認關閉)-f 在方法結束之后(正常返回和異常返回)觀察(默認開啟)-x 指定輸岀結果的屬性遍歷深度,默認為0
trace 方法內部調用路徑,并輸出方法路徑上的每個節點上耗時-n 執行次數限制
stack 輸出當前方法被調用的調用路徑
tt 方法執行數據的時空隧道,記錄下指定方法每次調用的入參和返回信息,并能對這些不同的時間下調用進行觀測
其他
jobs 列出所有job
kill 強制終止任務
fg 將暫停的任務拉到前臺執行
bg 將暫停的任務放到后臺執行
grep 搜索滿足條件的結果
plaintext 將命令的結果去除ANSI顏色
wc 按行統計輸出結果
options 查看或設置Arthas全局開關
profiler 使用async-profiler對應用采樣,生成火焰圖
19.7. Java Misssion Control
在Oracle收購Sun之前,Oracle的JRockit虛擬機提供了一款叫做 JRockit Mission Control 的虛擬機診斷工具。
在Oracle收購sun之后,Oracle公司同時擁有了Hotspot和 JRockit 兩款虛擬機。根據Oracle對于Java的戰略,在今后的發展中,會將JRokit的優秀特性移植到Hotspot上。其中一個重要的改進就是在Sun的JDK中加入了JRockit的支持。
在Oracle JDK 7u40之后,Mission Control這款工具己經綁定在Oracle JDK中發布。
Eclipse Mission Control下載
自Java11開始,本節介紹的JFR己經開源。但在之前的Java版本,JFR屬于Commercial Feature通過Java虛擬機參數-XX:+UnlockCommercialFeatures 開啟。
Java Mission Control(簡稱JMC) , Java官方提供的性能強勁的工具,是一個用于對 Java應用程序進行管理、監視、概要分析和故障排除的工具套件。它包含一個GUI客戶端以及眾多用來收集Java虛擬機性能數據的插件如 JMX Console(能夠訪問用來存放虛擬機齊個于系統運行數據的MXBeans)以及虛擬機內置的高效 profiling 工具 Java Flight Recorder(JFR)。
JMC的另一個優點就是:采用取樣,而不是傳統的代碼植入技術,對應用性能的影響非常非常小,完全可以開著JMC來做壓測(唯一影響可能是 full gc 多了)。
官方地址:https://github.com/JDKMissionControl/jmc
Java Flight Recorder
Java Flight Recorder是JMC的其中一個組件,能夠以極低的性能開銷收集Java虛擬機的性能數據。與其他工具相比,JFR的性能開銷很小,在默認配置下平均低于1%。JFR能夠直接訪問虛擬機內的敵據并且不會影響虛擬機的優化。因此它非常適用于生產環境下滿負荷運行的Java程序。
Java Flight Recorder 和 JDK Mission Control共同創建了一個完整的工具鏈。JDK Mission Control 可對 Java Flight Recorder 連續收集低水平和詳細的運行時信息進行高效、詳細的分析。
當啟用時 JFR將記錄運行過程中發生的一系列事件。其中包括Java層面的事件如線程事件、鎖事件,以及Java虛擬機內部的事件,如新建對象,垃圾回收和即時編譯事件。按照發生時機以及持續時間來劃分,JFR的事件共有四種類型,它們分別為以下四種:
- 瞬時事件(Instant Event) ,用戶關心的是它們發生與否,例如異常、線程啟動事件。
- 持續事件(Duration Event) ,用戶關心的是它們的持續時間,例如垃圾回收事件。
- 計時事件(Timed Event) ,是時長超出指定閾值的持續事件。
- 取樣事件(Sample Event),是周期性取樣的事件。
取樣事件的其中一個常見例子便是方法抽樣(Method Sampling),即每隔一段時問統計各個線程的棧軌跡。如果在這些抽樣取得的棧軌跡中存在一個反復出現的方法,那么我們可以推測該方法是熱點方法
19.8. 其他工具
Flame Graphs(火焰圖)
在追求極致性能的場景下,了解你的程序運行過程中cpu在干什么很重要,火焰圖就是一種非常直觀的展示CPU在程序整個生命周期過程中時間分配的工具。火焰圖對于現代的程序員不應該陌生,這個工具可以非常直觀的顯示出調用找中的CPU消耗瓶頸。
網上的關于Java火焰圖的講解大部分來自于Brenden Gregg的博客 http://new.brendangregg.com/flamegraphs.html
火焰圖,簡單通過x軸橫條寬度來度量時間指標,y軸代表線程棧的層次。
Tprofiler
案例: 使用JDK自身提供的工具進行JVM調優可以將下 TPS 由2.5提升到20(提升了7倍),并準確 定位系統瓶頸。
系統瓶頸有:應用里釋態對象不是太多、有大量的業務線程在頻繁創建一些生命周期很長的臨時對象,代碼里有問題。
那么,如何在海量業務代碼里邊準確定位這些性能代碼?這里使用阿里開源工具 Tprofiler 來定位 這些性能代碼,成功解決掉了GC 過于頻繁的性能瓶預,并最終在上次優化的基礎上將 TPS 再提升了4倍,即提升到100。
- Tprofiler配置部署、遠程操作、 日志閱談都不太復雜,操作還是很簡單的。但是其卻是能夠 起到一針見血、立竿見影的效果,幫我們解決了GC過于頻繁的性能瓶預。
- Tprofiler最重要的特性就是能夠統汁出你指定時間段內 JVM 的 top method 這些 top method 極有可能就是造成你 JVM 性能瓶頸的元兇。這是其他大多數 JVM 調優工具所不具備的,包括 JRockit Mission Control。JRokit 首席開發者 Marcus Hirt 在其私人博客《 Lom Overhead Method Profiling cith Java Mission Control》下的評論中曾明確指出 JRMC 井不支持 TOP 方法的統計。
官方地址:http://github.com/alibaba/Tprofiler
Btrace
常見的動態追蹤工具有BTrace、HouseHD(該項目己經停止開發)、Greys-Anatomy(國人開發 個人開發者)、Byteman(JBoss出品),注意Java運行時追蹤工具井不限干這幾種,但是這幾個是相對比較常用的。
BTrace是SUN Kenai 云計算開發平臺下的一個開源項目,旨在為java提供安全可靠的動態跟蹤分析工具。先看一卜日Trace的官方定義:
大概意思是一個 Java 平臺的安全的動態追蹤工具,可以用來動態地追蹤一個運行的 Java 程序。BTrace動態調整目標應用程序的類以注入跟蹤代碼(“字節碼跟蹤“)。
YourKit
JProbe
Spring Insight