JVM性能調(diào)優(yōu)

編譯器

查詢運(yùn)行模式

java -version
截屏2022-09-22 上午10.56.26.png
  • mixed mode 混合模式
    設(shè)置編譯模式
java -Xint -version
截屏2022-09-22 上午10.58.50.png
  • -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 )
  1. 用于統(tǒng)計(jì)一個(gè)方法中循環(huán)體代碼執(zhí)行的次數(shù),在字節(jié)碼中遇到控制流向后跳轉(zhuǎn)的指令稱為“回邊”( Back Edge )叭喜。在不開啟分層編譯的情況下, C1編譯器下的默認(rèn)閾值13995 , C2默認(rèn)為10700,
    可使用:XX:OnStackReplacePercentage= X指定閾值
  2. 建立回邊計(jì)數(shù)器的主要目的是為了觸發(fā)OSR ( On StackReplacement )編譯,參考文檔
  3. 當(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ù)器流程

截屏2022-09-22 下午1.57.06.png

方法調(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ù)器流程

截屏2022-09-22 下午2.08.51.png
參數(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)條件
  1. 方法體足夠小
  • 熱點(diǎn)方法:如果方法體小于325字節(jié)會(huì)嘗試內(nèi)聯(lián),可用-XX:FreqInlineSize修改大小
  • 非熱點(diǎn)方法:如果方法體小于35字節(jié),會(huì)嘗試內(nèi)聯(lián),可用-XX:MaxInlineSize修改大小
  1. 被調(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)
  1. 盡量讓方法體小一些
  2. 盡量使用final级乍、private舌劳、 static 關(guān)鍵字修飾方法, 避免因?yàn)槎鄳B(tài),需要對(duì)方法做額外的檢查
  3. 一些場(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)記
  1. 全局級(jí)別逃逸:一個(gè)對(duì)象可能從方法或者當(dāng)前線程中逃逸
  • 對(duì)象被作為方法的返回值
  • 對(duì)象作為靜態(tài)字段(static field)或者成員變量( field)
  • 如果重寫了某個(gè)類的finalize()方法,那么這個(gè)類的對(duì)象都會(huì)被標(biāo)記為全局逃逸狀態(tài)并且一定會(huì)放在堆內(nèi)存中
  1. 參數(shù)級(jí)別逃逸
  • 對(duì)象被作為參數(shù)傳遞給一個(gè)方法,但是在這個(gè)方法之外無法訪問/對(duì)其他線程不可見
  • 無逃逸:一個(gè)對(duì)象不會(huì)逃逸
標(biāo)量替換
  1. 通過逃逸分析確定該對(duì)象不會(huì)被外部訪問,并且對(duì)象可以被進(jìn)一步分解時(shí), JVM不會(huì)創(chuàng)建該對(duì)象,而是創(chuàng)建它的成員變量來代替
  2. XX:+EliminateAllocations開啟標(biāo)量替換( JDK 8默認(rèn)開啟)
  • 標(biāo)量:不能被進(jìn)一步分解的量
    1. 基礎(chǔ)數(shù)據(jù)類型
    2. 對(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)存性能問題捐晶。


內(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ù)

截屏2022-11-03 上午11.43.56.png

  • -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>】

截屏2022-11-03 上午11.46.42.png

  • 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>]】

截屏2022-11-03 上午11.45.09.png

  • Compiled:已執(zhí)行的編譯數(shù)
  • Failed :失敗的編譯數(shù)
  • Invalid :無效的編譯數(shù)
  • Time :執(zhí)行編譯的總時(shí)間
  • FailedType :最后一次失敗編譯的編譯類型
  • FailedMethod:最后-次編譯失敗的類名和方法

查看內(nèi)存使用和GC情況
【jstat -gc <pid> [<interval> [<count>]】

截屏2022-11-03 上午11.47.39.png

  • 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>]】

截屏2022-11-03 下午12.20.06.png

  • 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基本一致,多了最后兩列


截屏2022-11-03 下午12.21.30.png
  • LGCC:.上一次垃圾收集發(fā)生的原因
  • GCC :本次垃圾收集發(fā)生的原因

各年代內(nèi)存池和空間容量
【jstat -gccapacity <pid>】

截屏2022-11-03 下午12.23.04.png

  • 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>】

截屏2022-11-03 下午12.26.56.png

  • 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,表示只在第一行顯示一次列表頭


    截屏2022-11-03 下午1.40.48.png
  • -t
    在輸出內(nèi)容的第一列顯示 timestamp列,表示當(dāng)前JVM啟動(dòng)的時(shí)間


    截屏2022-11-03 下午1.41.20.png

故障排查工具

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>】
官方文檔

  • 用法


    截屏2022-11-03 下午1.42.11.png
  • 參數(shù)說明
  1. pid: 對(duì)應(yīng)jvm的進(jìn)程id
  2. executable core: 產(chǎn)生core dump文件
  3. [server-id@]remote server IP or hostname: 遠(yuǎn)程的ip或者h(yuǎn)ostname乘瓤,server-id標(biāo)記服務(wù)的唯一性id
  • option
  1. no option:輸出全部的參數(shù)和系統(tǒng)屬性
  2. flag name:輸出對(duì)應(yīng)名稱的參數(shù)
  3. flag [+|-]name:開啟或者關(guān)閉對(duì)應(yīng)名稱的參數(shù)
  4. flag name=value:設(shè)定對(duì)應(yīng)名稱的參數(shù)
  5. -flags:輸出全部的參數(shù)
  6. sysprops:輸出系統(tǒng)屬性
    具體參考
jmap

使用 jmap 可查看堆內(nèi)存初始化配置信息以及堆內(nèi)存的使用情況环形,輸出堆內(nèi)存中的對(duì)象信息,包括產(chǎn)生了哪些對(duì)象衙傀,對(duì)象數(shù)量多少等抬吟。
用法

截屏2022-11-03 下午1.43.19.png

  • 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

  1. <no option> : jmap <pid> 沒有option參數(shù)火本,jmap命令輸出共享對(duì)象映射信息。會(huì)輸出JVM中所有共享對(duì)象的起始地址聪建、映射大小钙畔、文件的全路徑
    截屏2022-11-03 下午1.43.50.png

    -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)容

  1. heap : 輸出堆垃圾回收的摘要信息挥下,配置信息叔锐,各年代的堆使用信息以及 interned Strings的是數(shù)量和大小挪鹏。
  2. histo[:live]
  • 將堆信息以列表(histogram)的形式輸出;
  • 輸出每個(gè)類的信息:對(duì)象個(gè)數(shù)愉烙、內(nèi)存字節(jié)數(shù)讨盒、全路徑;
  • 如果指定live步责,只統(tǒng)計(jì)活躍對(duì)象信息
  1. clstats
  • 輸出Java堆中類加載器的統(tǒng)計(jì)信息返顺;
  • 輸出每個(gè)類加載器的信息:名稱,狀態(tài)蔓肯,地址遂鹊,父類加載器,已加載的類的數(shù)量和大姓岚秉扑;
  • 統(tǒng)計(jì)會(huì)比較耗費(fèi)時(shí)間;
  1. F
    強(qiáng)制輸出
  • 使用jmap -dump或者jmap -histo命令時(shí)调限,如果進(jìn)程沒有響應(yīng)舟陆,可以使用-F強(qiáng)制輸出;
  • live模式下不能使用-F強(qiáng)制輸出耻矮;
    h help
  • -h與-help都是輸出幫助信息的指令
  1. -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)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末溢吻,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子果元,更是在濱河造成了極大的恐慌促王,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,402評(píng)論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件噪漾,死亡現(xiàn)場(chǎng)離奇詭異硼砰,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)欣硼,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門题翰,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人诈胜,你說我怎么就攤上這事豹障。” “怎么了焦匈?”我有些...
    開封第一講書人閱讀 162,483評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵血公,是天一觀的道長。 經(jīng)常有香客問我缓熟,道長累魔,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,165評(píng)論 1 292
  • 正文 為了忘掉前任够滑,我火速辦了婚禮垦写,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘彰触。我一直安慰自己梯投,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,176評(píng)論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著分蓖,像睡著了一般尔艇。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上么鹤,一...
    開封第一講書人閱讀 51,146評(píng)論 1 297
  • 那天终娃,我揣著相機(jī)與錄音,去河邊找鬼午磁。 笑死尝抖,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的迅皇。 我是一名探鬼主播昧辽,決...
    沈念sama閱讀 40,032評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼登颓!你這毒婦竟也來了搅荞?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,896評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤框咙,失蹤者是張志新(化名)和其女友劉穎咕痛,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體喇嘱,經(jīng)...
    沈念sama閱讀 45,311評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡茉贡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,536評(píng)論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了者铜。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片腔丧。...
    茶點(diǎn)故事閱讀 39,696評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖作烟,靈堂內(nèi)的尸體忽然破棺而出愉粤,到底是詐尸還是另有隱情,我是刑警寧澤拿撩,帶...
    沈念sama閱讀 35,413評(píng)論 5 343
  • 正文 年R本政府宣布衣厘,位于F島的核電站,受9級(jí)特大地震影響压恒,放射性物質(zhì)發(fā)生泄漏影暴。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,008評(píng)論 3 325
  • 文/蒙蒙 一探赫、第九天 我趴在偏房一處隱蔽的房頂上張望型宙。 院中可真熱鬧,春花似錦期吓、人聲如沸早歇。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽箭跳。三九已至,卻和暖如春潭千,著一層夾襖步出監(jiān)牢的瞬間谱姓,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評(píng)論 1 269
  • 我被黑心中介騙來泰國打工刨晴, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留屉来,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,698評(píng)論 2 368
  • 正文 我出身青樓狈癞,卻偏偏與公主長得像茄靠,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子蝶桶,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,592評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容