編譯器
查詢運(yùn)行模式
java -version
- mixed mode 混合模式
設(shè)置編譯模式
java -Xint -version
- -Xint :設(shè)置JVM的執(zhí)行模式為解釋執(zhí)行模式
- -Xcomp : JVM優(yōu)先以編譯模式運(yùn)行,不能編譯的航徙,以解釋模式運(yùn)行。
- -Xmixed :混合模式運(yùn)行
一般情況下
一開始一 般由解釋器解釋執(zhí)行
當(dāng)虛擬機(jī)發(fā)現(xiàn)某個(gè)方法或代碼塊的運(yùn)行特別頻繁的時(shí)候,就會(huì)認(rèn)為這些代碼是 “熱點(diǎn)代碼”。為了提高熱點(diǎn)代碼的執(zhí)行效率,會(huì)用即時(shí)編譯器(也就是JIT )把這些熱點(diǎn)代碼編譯成與本地平臺(tái)相關(guān)的機(jī)器碼,并進(jìn)行各層次的優(yōu)化
Hotspot的即時(shí)編譯器
C1編譯器:
是一個(gè)簡(jiǎn)單快速的編譯器,主要關(guān)注局部性的優(yōu)化,適用于執(zhí)行時(shí)間較短或?qū)?dòng)性能有要求的程序谣膳。例如场绿,GUI,應(yīng)用對(duì)界面啟動(dòng)速度就有一定要求。
也被稱為是Client Compiler
C2編譯器:
是為長期運(yùn)行的服務(wù)器端應(yīng)用程序做性能調(diào)優(yōu)的編譯器,適用于執(zhí)行時(shí)間較長或?qū)Ψ逯敌阅苡幸蟮某绦?br> 也被稱為是Server Compiler
并進(jìn)行各層次的優(yōu)化
分層編譯
- 0 :解釋執(zhí)行
- 1 :簡(jiǎn)單C1編譯:會(huì)用C1編譯器進(jìn)行一些簡(jiǎn)單的優(yōu)化 ,不開啟Profiling
- 2 :受限的C1編譯:僅執(zhí)行帶方法調(diào)用次數(shù)以及循環(huán)回邊執(zhí)行次數(shù)Profiling的C1編譯
- 3 :完全C1編譯:會(huì)執(zhí)行帶有所有Profiling的C1代碼
- 4 : C2編譯:使用C2編譯器進(jìn)行優(yōu)化,該級(jí)別會(huì)啟用一些編譯耗時(shí)較長的優(yōu)化,一些情況下會(huì)根據(jù)性能監(jiān)控信息進(jìn)行一些非常激進(jìn)的性能優(yōu)化
級(jí)別越高,應(yīng)用啟動(dòng)越慢,優(yōu)化的開銷越高,峰值性能也越高脏里。
分層編譯-JVM參數(shù)配置示例
- 只想開啟C2 : -XX:-TieredCompilation (禁用中間編譯層( 123層) )
- 只想開啟C1 : -XX:+ TieredCompilation -XX:TieredStopAtLevel=1
如何找到熱點(diǎn)代碼?思路是?
- 基于采樣的熱點(diǎn)探測(cè)
- 基于計(jì)數(shù)器的熱點(diǎn)探測(cè)
Hotspot內(nèi)置的兩類計(jì)數(shù)器
- 方法調(diào)用計(jì)數(shù)器( Invocation Counter )
用于統(tǒng)計(jì)方法被調(diào)用的次數(shù),在不開啟分層編譯的情況下踩麦,在C1編譯器下的默認(rèn)閾值是1 500次,在C2模式下是10000次。
也可用-XX:CompileThreshold =X指定閾值
- 回邊計(jì)數(shù)器( Back Edge Counter )
- 用于統(tǒng)計(jì)一個(gè)方法中循環(huán)體代碼執(zhí)行的次數(shù),在字節(jié)碼中遇到控制流向后跳轉(zhuǎn)的指令稱為“回邊”( Back Edge )叭喜。在不開啟分層編譯的情況下, C1編譯器下的默認(rèn)閾值13995 , C2默認(rèn)為10700,
可使用:XX:OnStackReplacePercentage= X指定閾值- 建立回邊計(jì)數(shù)器的主要目的是為了觸發(fā)OSR ( On StackReplacement )編譯,參考文檔
- 當(dāng)開啟分層編譯時(shí), JVM會(huì)根據(jù)當(dāng)前待編譯的方法數(shù)以及編譯線程數(shù)來動(dòng)態(tài)調(diào)整閾值, -XX: CompileThreshold贺拣、-XX:
OnStackReplacePercentage都會(huì)失效。
方法調(diào)用計(jì)數(shù)器流程
方法調(diào)用計(jì)數(shù)器
如果不做任何設(shè)置,方法調(diào)用計(jì)數(shù)器統(tǒng)計(jì)的并不是方法被調(diào)用的絕對(duì)次數(shù),而是一個(gè)相對(duì)的執(zhí)行頻率捂蕴,即一段時(shí)間之內(nèi)方法被調(diào)用的數(shù)譬涡。當(dāng)超過一定的時(shí)間限度,如果方法的調(diào)用次數(shù)仍然不足以讓它提交給即時(shí)編譯器編譯,那這個(gè)方法的調(diào)用計(jì)數(shù)器就會(huì)被減少一半,這個(gè)過程稱為方法調(diào)用計(jì)數(shù)器熱度的衰減,而這段時(shí)間就稱為此方法統(tǒng)計(jì)的半衰周期裳凸。進(jìn)行熱度衰減的動(dòng)作是在虛擬機(jī)進(jìn)行垃圾收集時(shí)順便進(jìn)行的,可以使用虛擬機(jī)參數(shù).XX: -UseCounterDecay來關(guān)閉熱度衰減,讓方法計(jì)數(shù)器統(tǒng)計(jì)方法調(diào)用的絕對(duì)次數(shù),這樣,只要系統(tǒng)運(yùn)行時(shí)間足夠長,絕大部分方法都會(huì)被編譯成本地代碼秘蛇。另外,可以使用-XX:CounterHalfLifeTime參數(shù)設(shè)置半衰周期的時(shí)間 ,單位是秒
回邊計(jì)數(shù)器流程
參數(shù)總結(jié)
- -Xmixed :混合模式運(yùn)行(默認(rèn))
- -Xint :設(shè)置JVM的執(zhí)行模式為解釋執(zhí)行模式
- -Xcomp :JVM優(yōu)先以編譯模式運(yùn)行蜕该,不能編譯的坑夯,以解釋模式運(yùn)行徐裸。
- -XX:-TieredCompilation :禁用中間編譯層
- -XX:TieredStopAtLevel :到哪個(gè)分層停止
- -XX:CompileThreshold=X :指定方法調(diào)用計(jì)數(shù)器閾值(關(guān)閉分層編譯時(shí)才有效)
- -XX:OnStackReplacePercentage=X :指定回邊計(jì)數(shù)器閾值(關(guān)閉分層編譯時(shí)才有效)
- -XX:-UseCounterDecay :關(guān)閉方法調(diào)用計(jì)數(shù)器熱度衰減
- -XX:CounterHalfLifeTime :指定方法調(diào)用計(jì)數(shù)器半衰周期(秒)
編譯器優(yōu)化-方法內(nèi)聯(lián)
把目標(biāo)方法的代碼復(fù)制到發(fā)起調(diào)用的方法之中,避免發(fā)生真實(shí)的方法調(diào)用
方法內(nèi)聯(lián)條件
- 方法體足夠小
- 熱點(diǎn)方法:如果方法體小于325字節(jié)會(huì)嘗試內(nèi)聯(lián),可用-XX:FreqInlineSize修改大小
- 非熱點(diǎn)方法:如果方法體小于35字節(jié),會(huì)嘗試內(nèi)聯(lián),可用-XX:MaxInlineSize修改大小
- 被調(diào)用方法運(yùn)行時(shí)的實(shí)現(xiàn)被可以唯一確定
- static方法猖腕、private方法及final方法 , JIT可以唯一確定具體的實(shí)現(xiàn)代碼
- public的實(shí)例方法,指向的實(shí)現(xiàn)可能是自身刃宵、父類逊脯、子類的代碼,當(dāng)且僅當(dāng)JIT能夠唯一確定方法的具體實(shí)現(xiàn)時(shí),才有可能完成內(nèi)聯(lián)
方法內(nèi)聯(lián)注意點(diǎn)
- 盡量讓方法體小一些
- 盡量使用final级乍、private舌劳、 static 關(guān)鍵字修飾方法, 避免因?yàn)槎鄳B(tài),需要對(duì)方法做額外的檢查
- 一些場(chǎng)景下,可通過JVM參數(shù)修改閾值,從而讓更多方法內(nèi)聯(lián)
內(nèi)聯(lián)可能帶來的問題
CodeCache的溢出,導(dǎo)致JVM退化成解釋執(zhí)行模式
內(nèi)聯(lián)相關(guān)JVM參數(shù)
- -XX:MaxTrivialSize=n :默認(rèn) 6,如果方法的字節(jié)碼少于該值玫荣,則直接內(nèi)聯(lián)甚淡,單位字節(jié)
- -XX:MinInliningThreshold=n :默認(rèn) 250,如果目標(biāo)方法的調(diào)用次數(shù)低于該值捅厂,則不去內(nèi)聯(lián)
- -XX:LiveNodeCountInliningCutoff=n :默認(rèn) 40000贯卦,編譯過程中最大活動(dòng)節(jié)點(diǎn)數(shù)(IR節(jié)點(diǎn))的上限,僅對(duì)C2編譯器有效
- -XX:InlineFrequencyCount=n :默認(rèn) 100焙贷,如果方法的調(diào)用點(diǎn)(call site)的執(zhí)行次數(shù)超過該值撵割,則觸發(fā)內(nèi)聯(lián)
- -XX:MaxRecursiveInlineLevel=n :默認(rèn) 1,遞歸調(diào)用大于這么多次就不內(nèi)聯(lián)
- -XX:+lnlineSynchronizedMethods :默認(rèn) 開啟辙芍,是否允許內(nèi)聯(lián)同步方法
逃逸分析啡彬,標(biāo)量替換,棧上分配
標(biāo)量:不能被進(jìn)一步分解的量
●基礎(chǔ)數(shù)據(jù)類型
●對(duì)象引用
聚合量:可以進(jìn)一步分解的量故硅,棧上分配
分析變量能否逃出它的作用域
逃逸分析
- 全局變量賦值逃逸
例:局部變量賦值給靜態(tài)變量
- 方法返回值逃逸
- 實(shí)例引用逃逸
- 線程逃逸
賦值給類變量或可以在其他線程中訪問的實(shí)例變量
逃逸狀態(tài)標(biāo)記
- 全局級(jí)別逃逸:一個(gè)對(duì)象可能從方法或者當(dāng)前線程中逃逸
- 對(duì)象被作為方法的返回值
- 對(duì)象作為靜態(tài)字段(static field)或者成員變量( field)
- 如果重寫了某個(gè)類的finalize()方法,那么這個(gè)類的對(duì)象都會(huì)被標(biāo)記為全局逃逸狀態(tài)并且一定會(huì)放在堆內(nèi)存中
- 參數(shù)級(jí)別逃逸
- 對(duì)象被作為參數(shù)傳遞給一個(gè)方法,但是在這個(gè)方法之外無法訪問/對(duì)其他線程不可見
- 無逃逸:一個(gè)對(duì)象不會(huì)逃逸
標(biāo)量替換
- 通過逃逸分析確定該對(duì)象不會(huì)被外部訪問,并且對(duì)象可以被進(jìn)一步分解時(shí), JVM不會(huì)創(chuàng)建該對(duì)象,而是創(chuàng)建它的成員變量來代替
- XX:+EliminateAllocations開啟標(biāo)量替換( JDK 8默認(rèn)開啟)
- 標(biāo)量:不能被進(jìn)一步分解的量
- 基礎(chǔ)數(shù)據(jù)類型
- 對(duì)象引用
- 聚合量:可以進(jìn)一步分解的量
例:
Study study = new Study();
study.id = 1;
study.age = 1;
//開啟標(biāo)量替換后
int id = 1;
int age = 1;
棧上分配
通過逃逸分析外遇,能夠確認(rèn)對(duì)象不會(huì)被外部訪問,就在棧上分配對(duì)象
相關(guān)JVM參數(shù)
- -XX:+DoEscapeAnalysis :默認(rèn) 開啟,是否開啟逃逸分析
- -XX:+ EliminateAllocations :默認(rèn) 開啟契吉,是否開啟標(biāo)量替換
- -XX:+ EliminateLocks :默認(rèn) 開啟跳仿,是否開
- 啟鎖消除
垃圾回收
相關(guān)知識(shí)點(diǎn)
參考基礎(chǔ)面試題大全主要知識(shí)點(diǎn)復(fù)習(xí)總結(jié)中JVM虛擬機(jī)部分
參考JVM知識(shí)整理
垃圾收集器相關(guān)JVM參數(shù)總結(jié)
從實(shí)際案例聊聊Java應(yīng)用的GC優(yōu)化
JVM調(diào)優(yōu)工具錦囊
JVM調(diào)優(yōu)工具及案例分析
性能調(diào)優(yōu)工具
利用工具調(diào)優(yōu)分析問題
JVM調(diào)優(yōu)
JVM調(diào)優(yōu)-內(nèi)置工具
JDK工具
JDK自帶了很多性能監(jiān)控工具,我們可以用這些工具來監(jiān)測(cè)系統(tǒng)和排查內(nèi)存性能問題捐晶。
監(jiān)控工具
jps
jps(Java Virtual Machine Process Status Tool)是JDK 1.5提供的一個(gè)顯示當(dāng)前所有java進(jìn)程pid的命令菲语。
相關(guān)命令
- jps -q :只顯示進(jìn)程號(hào)
- jps -m :顯示傳遞給main方法的參數(shù)
- jps -l :顯示應(yīng)用main class的完整包名應(yīng)用的jar文件完整路徑名
- jps -v :顯示傳遞給jvm的參數(shù)
- jps -V :禁止輸出類名妄辩、jar文件名和傳遞給main方法的參數(shù),僅顯示本地jvm標(biāo)識(shí)符列表
命令混合使用:
示例:
- jps -l -v
- jps -m -l -v
- jps -ml
- jps -vl 輸出傳遞給JVM的參數(shù)
和jps功能類似的有
- ps -ef | grep java
- ps aux | grep java
jstat
使用 jstat 工具可以監(jiān)測(cè) Java 應(yīng)用程序的實(shí)時(shí)運(yùn)行情況山上,可以看到VM內(nèi)的Eden眼耀、Survivor、老年代的內(nèi)存使用情況佩憾,還有 YoungGC 和 FullGC 的執(zhí)行次數(shù)以及耗時(shí)哮伟。通過這些指標(biāo),我們可以輕松的分析出當(dāng)前系統(tǒng)的運(yùn)行情況妄帘,判斷當(dāng)前系統(tǒng)的內(nèi)存使用壓力以及GC壓力楞黄,還有內(nèi)存分配是否合理。
查看官網(wǎng)jstat及相關(guān)命令
語法
jstat [ generalOption | outputOptions [-t] [-h<lines>] vmid [ interval[s|ms] [count] ]
- interval 單位是毫秒抡驼,每過多久打印一次
- count 打印多少次鬼廓,默認(rèn)一個(gè)參數(shù)是interval
- -t 程序從開始執(zhí)行到現(xiàn)在過了多少時(shí)間 ms
- -h 每個(gè)多少多少條打印一次表頭
generalOption
單個(gè)常規(guī)命令
- jstat -help :展示幫助信息
- jstat -options :展示所有的靜態(tài)列表選項(xiàng)
相關(guān)命令
【jstat -options】
將javaOptions參數(shù)傳遞給Java應(yīng)用。查看完整Java參數(shù)
- -class:顯示 ClassLoad 的相關(guān)信息致盟;
- -compiler:顯示 JIT 編譯的相關(guān)信息碎税;
- -gc:顯示和 gc 相關(guān)的堆信息;
- -gccapacity:顯示各個(gè)代的容量以及使用情況馏锡;
- -gcmetacapacity:顯示 Metaspace 的大欣柞濉;
- -gcnew:顯示新生代信息杯道;
- -gcnewcapacity:顯示新生代大小和使用情況萎河;
- -gcold:顯示老年代和永久代的信息;
- -gcoldcapacity :顯示老年代的大薪侗;
- -gcutil:顯示垃圾收集信息玛歌;
- -gccause:顯示垃圾回收的相關(guān)信息(同 -gcutil)昧港,同時(shí)顯示最后一次或當(dāng)前正在發(fā)生的垃圾回收的誘因;
- -printcompilation:輸出 JIT 編譯的方法信息
其中 jstat -gc 是最完整支子、最常用创肥、最實(shí)用的命令,基本足夠分析jvm的運(yùn)行情況了值朋。
顯示 ClassLoad 的相關(guān)信息
【jstat -class <pid>】
- Loaded : 已加載的類個(gè)數(shù)
- Bytes : 已加載的字節(jié)數(shù)(kb)
- Unloaded : 未加載的類個(gè)數(shù)
- Bytes : 未加載的字節(jié)數(shù)(kb)
- Time : Time spent performing class loading and unloading operations
Java HotSpot VM即時(shí)編譯器
【jstat -compiler <pid> [<interval> [<count>]】
- Compiled:已執(zhí)行的編譯數(shù)
- Failed :失敗的編譯數(shù)
- Invalid :無效的編譯數(shù)
- Time :執(zhí)行編譯的總時(shí)間
- FailedType :最后一次失敗編譯的編譯類型
- FailedMethod:最后-次編譯失敗的類名和方法
查看內(nèi)存使用和GC情況
【jstat -gc <pid> [<interval> [<count>]】
- S0C:年輕代中 To Survivor 的容量(單位 KB)叹侄;
- S1C:年輕代中 From Survivor 的容量(單位 KB);
- S0U:年輕代中 To Survivor 目前已使用空間(單位 KB)昨登;
- S1U:年輕代中 From Survivor 目前已使用空間(單位 KB)趾代;
- EC:年輕代中 Eden 的容量(單位 KB);
- EU:年輕代中 Eden 目前已使用空間(單位 KB)丰辣;
- OC:老年代的容量(單位 KB)撒强;
- OU:老年代目前已使用空間(單位 KB)禽捆;
- MC:Metaspace 的容量(單位 KB);
- MU:Metaspace 目前已使用空間(單位 KB)飘哨;
- CCSC:壓縮類空間大小
- CCSU:壓縮類空間使用大小
- YGC:從應(yīng)用程序啟動(dòng)到采樣時(shí)年輕代中 gc 次數(shù)胚想;
- YGCT:從應(yīng)用程序啟動(dòng)到采樣時(shí)年輕代中 gc 所用時(shí)間 (s);
- FGC:從應(yīng)用程序啟動(dòng)到采樣時(shí) old 代(全 gc)gc 次數(shù)芽隆;
- FGCT:從應(yīng)用程序啟動(dòng)到采樣時(shí) old 代(全 gc)gc 所用時(shí)間 (s)浊服;
- GCT:從應(yīng)用程序啟動(dòng)到采樣時(shí) gc 用的總時(shí)間 (s)
查看垃圾回收統(tǒng)計(jì)
【jstat -gcutil <pid> [<interval> [<count>]】
- S0:Survivor0 區(qū)占用百分比
- S1:Survivor1 區(qū)占用百分比
- E:Eden 區(qū)占用百分比
- O:老年代占用百分比
- M:元數(shù)據(jù)區(qū)占用百分比
- YGC:年輕代回收次數(shù)
- YGCT:年輕代回收耗時(shí)
- FGC:老年代回收次數(shù)
- FGCT:老年代回收耗時(shí)
- GCT:GC總耗時(shí)
【jstat -gccause <pid>】
這個(gè)參數(shù)展示的垃圾收集信息與-gcutil基本一致,多了最后兩列
- LGCC:.上一次垃圾收集發(fā)生的原因
- GCC :本次垃圾收集發(fā)生的原因
各年代內(nèi)存池和空間容量
【jstat -gccapacity <pid>】
- NGCMN: 最小青年代容量(kb)
- NGCMX: 最大青年代容量(kb)
- NGC:當(dāng)前青年代大小(kb)
- SOC: survivor 0空間容量(kb)
- S1C : survivor 1空間容量(kb)
- EC : eden空間容量(kb)
- OGCMN:最小老年代容量(kb)
- OGCMX: 最大老年代容量(kb)
- OGC: 當(dāng)前老年代容量(kb)
- 0C: old空間容量(kb)
- MCMN: 最小metaspace容量(kb)
- MCMX :最大metaspace容量(kb)
- MC: metaspace容量(kb)
- CCSMN: 最小壓縮類空間容量(kb)
- CCSMX: 最大壓縮類空間容量(kb)
- CCSC :壓縮類空間容量(kb)
- YGC :年輕代GC次數(shù)
- FGC: full GC次數(shù)
Java HotSpot 虛擬機(jī)編譯方法統(tǒng)計(jì)信息
【jstat -printcompilation <pid>】
- Compiled :最近的編譯方法執(zhí)行的編譯數(shù)(Number of compilation tasks performed by the most recently compiled method)
- Size :最近編譯的方法的字節(jié)碼的字節(jié)數(shù)( Number of bytes of byte code of the most recently compiled method)
- Type :最近編譯方法的編譯類型
- Method: 最近編譯方法的類名和方法胚吁。類路徑中用/代替.牙躺, 這個(gè)兩個(gè)字段的格式與
HotSpot的-XX:+PrintCompilation 參數(shù)一致。
outputOtions
輸出選項(xiàng)決定了jstat命令輸出的內(nèi)容和格式囤采,必須有一個(gè)statOption述呐,后面可以任意追加-h -t -J參數(shù)。
輸出內(nèi)容以表格形式展現(xiàn)蕉毯,第一行表示每列的意思乓搬。
-
-h n
每多少行顯示一次列表頭,默認(rèn)是0,表示只在第一行顯示一次列表頭
-
-t
在輸出內(nèi)容的第一列顯示 timestamp列,表示當(dāng)前JVM啟動(dòng)的時(shí)間
故障排查工具
jinfo
jinfo 是 JDK 自帶的命令代虾,可以用來查看正在運(yùn)行的 java 應(yīng)用程序的擴(kuò)展參數(shù)进肯,包括Java System屬性和JVM命令行參數(shù);
也可以動(dòng)態(tài)的修改正在運(yùn)行的 JVM 一些參數(shù)棉磨。
當(dāng)系統(tǒng)崩潰時(shí)江掩,jinfo可以從core文件里面知道崩潰的Java應(yīng)用程序的配置信息。
【jinfo <option> <pid>】
官方文檔
-
用法
- 參數(shù)說明
- pid: 對(duì)應(yīng)jvm的進(jìn)程id
- executable core: 產(chǎn)生core dump文件
- [server-id@]remote server IP or hostname: 遠(yuǎn)程的ip或者h(yuǎn)ostname乘瓤,server-id標(biāo)記服務(wù)的唯一性id
- option
- no option:輸出全部的參數(shù)和系統(tǒng)屬性
- flag name:輸出對(duì)應(yīng)名稱的參數(shù)
- flag [+|-]name:開啟或者關(guān)閉對(duì)應(yīng)名稱的參數(shù)
- flag name=value:設(shè)定對(duì)應(yīng)名稱的參數(shù)
- -flags:輸出全部的參數(shù)
- sysprops:輸出系統(tǒng)屬性
具體參考
jmap
使用 jmap 可查看堆內(nèi)存初始化配置信息以及堆內(nèi)存的使用情況环形,輸出堆內(nèi)存中的對(duì)象信息,包括產(chǎn)生了哪些對(duì)象衙傀,對(duì)象數(shù)量多少等抬吟。
用法
- executable : 產(chǎn)生核心轉(zhuǎn)儲(chǔ)的Java可執(zhí)行文件
- core : 打印內(nèi)存信息的核心文件
- remote-hostname-or-IP : 遠(yuǎn)程調(diào)試服務(wù)器的hostname或者IP地址。查看jsadebug
- server-id : 遠(yuǎn)程服務(wù)器上有多個(gè)調(diào)試服務(wù)器時(shí)统抬,提供的調(diào)式服務(wù)器唯一ID
- 通過
-J-d64可以指定jmap
運(yùn)行在64位JVM上 : jmap -J-d64 -heap pid
Options
- <no option> : jmap <pid> 沒有option參數(shù)火本,jmap命令輸出共享對(duì)象映射信息。會(huì)輸出JVM中所有共享對(duì)象的起始地址聪建、映射大小钙畔、文件的全路徑
-dump:[live,] format=b, file=*filename*
- 將Java堆信息存入filename指定文件名的hprof二進(jìn)制文件中;
- live 是可選操作金麸,指定live表示只保存活躍對(duì)象擎析;
- 使用jhat命令可以讀取文件;
$ jmap -dump:live,format=b,file=test 5208
Dumping heap to C:\user\username\Desktop\test ...
Heap dump file created
$ jhat C:\\Users\\username\\Desktop\\test
Reading from C:\Users\username\Desktop\test...
Dump file created Fri Dec 27 13:20:01 CST 2019
Snapshot read, resolving...
Resolving 502739 objects...
Chasing references, expect 100 dots....................................................................................................
Eliminating duplicate references....................................................................................................
Snapshot resolved.
Started HTTP server on port 7000
Server is ready.
訪問localhost:7000可以查看文件具體內(nèi)容
- heap : 輸出堆垃圾回收的摘要信息挥下,配置信息叔锐,各年代的堆使用信息以及 interned Strings的是數(shù)量和大小挪鹏。
- histo[:live]
- 將堆信息以列表(histogram)的形式輸出;
- 輸出每個(gè)類的信息:對(duì)象個(gè)數(shù)愉烙、內(nèi)存字節(jié)數(shù)讨盒、全路徑;
- 如果指定live步责,只統(tǒng)計(jì)活躍對(duì)象信息
- clstats
- 輸出Java堆中類加載器的統(tǒng)計(jì)信息返顺;
- 輸出每個(gè)類加載器的信息:名稱,狀態(tài)蔓肯,地址遂鹊,父類加載器,已加載的類的數(shù)量和大姓岚秉扑;
- 統(tǒng)計(jì)會(huì)比較耗費(fèi)時(shí)間;
- F
強(qiáng)制輸出
- 使用jmap -dump或者jmap -histo命令時(shí)调限,如果進(jìn)程沒有響應(yīng)舟陆,可以使用-F強(qiáng)制輸出;
- live模式下不能使用-F強(qiáng)制輸出耻矮;
h help
- -h與-help都是輸出幫助信息的指令
- -Jflag : 將flag信息傳遞給運(yùn)行jamp命令的虛擬機(jī)
查看堆內(nèi)存情況
【jmap -heap <PID>】
這個(gè)命令會(huì)打印出堆內(nèi)存相關(guān)的一些參數(shù)設(shè)置以及各個(gè)區(qū)域的情況秦躯,要查看這些信息一般使用 jstat 命令就足夠了。
查看系統(tǒng)運(yùn)行時(shí)對(duì)象分布
【jmap -histo[:live] <PID>】 帶上 live 則只統(tǒng)計(jì)活對(duì)象
這個(gè)命令會(huì)按照各種對(duì)象占用內(nèi)存空間的大小降序排列裆装,把占用內(nèi)存最多的對(duì)象放在最上面踱承。通過這個(gè)命令可以簡(jiǎn)單的了解下當(dāng)前jvm中的對(duì)象對(duì)內(nèi)存占用的情況以及當(dāng)前內(nèi)存里到底是哪個(gè)對(duì)象占用了大量的內(nèi)存空間。
生成堆內(nèi)存轉(zhuǎn)儲(chǔ)快照
【jmap -dump:format=b,file=<path> <pid>】
【jmap -dump:live,format=b,file=<path> <pid>】
jmap -dump 是輸出堆中所有對(duì)象哨免;
jmap -dump:live 是輸出堆中所有活著的對(duì)象茎活,而且 jmap -dump:live 會(huì)觸發(fā) FullGC,線上使用要注意琢唾。format=b 是以二進(jìn)制格式輸出载荔;file 是文件路徑,格式為 hrpof 后綴慧耍。
這個(gè)命令會(huì)在當(dāng)前目錄下生成一個(gè) dump.hrpof 文件,這是個(gè)二進(jìn)制的格式丐谋,無法直接打開芍碧,可以使用MAT等工具來分析。這個(gè)命令把這一時(shí)刻VM堆內(nèi)存里所有對(duì)象的快照放到文件里去了号俐,供你后續(xù)去分析泌豆。
jstack
jstack 是一種線程堆棧分析工具,最常用的功能就是使用 jstack pid 命令查看線程的堆棧信息吏饿,通常會(huì)結(jié)合 top -Hp pid 或 pidstat -p pid -t 一起查看具體線程的狀態(tài)踪危,也經(jīng)常用來排查一些死鎖的異常蔬浙、CPU占用高的線程等。
jstack參數(shù)
- -l:長列表. 打印關(guān)于鎖的附加信息贞远,例如屬于 java.util.concurrent 的 ownable synchronizers 列表畴博。
- -F:當(dāng) jstack [-l] pid 沒有響應(yīng)的時(shí)候強(qiáng)制打印棧信息
- -m:打印 java 和 native c/c++ 框架的所有棧信息.
- -h | -help:打印幫助信息
查看線程堆棧信息
【jstack <pid> > stack.log】
這個(gè)命令可以把程序的線程堆棧dump下來。每個(gè)線程堆棧的信息中蓝仲,都可以查看到線程 ID俱病、線程狀態(tài)(wait、sleep袱结、running 等狀態(tài))以及是否持有鎖等亮隙。
- pool-11-thread-6:線程名稱
-
1920:線程編號(hào)
- prio=5:線程的優(yōu)先級(jí)別
- os_prio=0:系統(tǒng)級(jí)別的線程優(yōu)先級(jí)
- tid=0x00007f87e028c000:線程ID
- nid=0x6724:native線程的id,通過 printf "%x\n" <pid> 命令轉(zhuǎn)換線程ID
- waiting on condition [0x00007f87b97d2000]:線程當(dāng)前的狀態(tài)
jcmd
jhat
分析Java堆內(nèi)存信息垢夹。
語法
【jhat [ options ] heap-dump-file】
參考
jhsdb
可視化工具
jhsdb
jconsole
VisualVM
Java Mission Control
其余參考
JVM調(diào)優(yōu)工具錦囊
JVM調(diào)優(yōu)工具及案例分析
性能調(diào)優(yōu)工具
利用工具調(diào)優(yōu)分析問題
JVM調(diào)優(yōu)