您好,登錄后才能下訂單哦!
這篇文章將為大家詳細(xì)講解有關(guān)帶你了解可視化JVM 故障處理工具,文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關(guān)知識有一定的了解。
1. 可視化工具
在 JDK 中為我們提供了大量的 JVM 故障處理工具,都在 JDK 的 bin 目錄下:
這其中除了大量的命令行工具以外,還為我們提供了更加方便快捷的可視化工具,主要是以下這 4 個:
2. HSDB
HSDB(Hotspot Debugger) 是 JDK 自帶的工具,用于查看 JVM 運(yùn)行時的狀態(tài)。
使用方式由于在 JDK 9 之前沒有正式提供,所以也未在 JDK 的 bin 目錄下提供直接可執(zhí)行文件,需要在命令行執(zhí)行命令才能啟動。
首先在命令行中先 cd 至 C:\Program Files\Java\jdk1.8.0_221\lib
目錄,然后執(zhí)行:
java -cp .\sa-jdi.jar sun.jvm.hotspot.HSDB
我在執(zhí)行這句命令的時候報了個錯:
Exception in thread "Thread-1" java.lang.UnsatisfiedLinkError: Can't load library: C:\Program Files\Java\jdk-11.0.4\bin\sawindbg.dll
at java.base/java.lang.ClassLoader.loadLibrary(ClassLoader.java:2620)
at java.base/java.lang.Runtime.load0(Runtime.java:767)
at java.base/java.lang.System.load(System.java:1831)
at sun.jvm.hotspot.debugger.windbg.WindbgDebuggerLocal.<clinit>(WindbgDebuggerLocal.java:661)
at sun.jvm.hotspot.HotSpotAgent.setupDebuggerWin32(HotSpotAgent.java:567)
at sun.jvm.hotspot.HotSpotAgent.setupDebugger(HotSpotAgent.java:335)
at sun.jvm.hotspot.HotSpotAgent.go(HotSpotAgent.java:304)
at sun.jvm.hotspot.HotSpotAgent.attach(HotSpotAgent.java:140)
at sun.jvm.hotspot.HSDB.attach(HSDB.java:1184)
at sun.jvm.hotspot.HSDB.access$1700(HSDB.java:53)
at sun.jvm.hotspot.HSDB$25$1.run(HSDB.java:456)
at sun.jvm.hotspot.utilities.WorkerThread$MainLoop.run(WorkerThread.java:66)
at java.base/java.lang.Thread.run(Thread.java:834)
含義是有一個 sawindbg.dll
在 jdk 的目錄下找不到,因?yàn)槲冶镜赜卸鄠€ jdk ,配置環(huán)境變量的是 jdk 11 ,我在 jdk 8 的 jre 的 bin 目錄下找到了這個文件,直接 copy 到 jdk 11 的bin 目錄下解決此問題。
執(zhí)行完成后會打開這么個界面:
接下來,我們寫一小段測試代碼:
public abstract class A { public void printMe() { System.out.println("I am A class"); } public abstract void sayHello(); } public class B extends A { @Override public void sayHello() { System.out.println("I am B class"); } } public class HSDB_Test { public static void main(String[] args) throws IOException { A obj = new B(); // 無意義,單純用作卡住主線程,防止線程結(jié)束 System.in.read(); System.out.println(obj); } }
首先在命令行中使用命令 jps -l
查看 Java 進(jìn)程的 pid :
PS C:\Users\inwsy> jps -l 1648 com.geekdigging.lesson04.jvmtools.HSDB_Test 8704 9280 org.jetbrains.jps.cmdline.Launcher 14724 jdk.jcmd/sun.tools.jps.Jps 3220 org/netbeans/Main 15144 20572 org.jetbrains.jps.cmdline.Launcher 7548 sun.jvm.hotspot.HSDB
可以看到,我們剛寫的測試方法的 pid 是 1648 ,在 HSDB 中點(diǎn)擊 File > Attach to Hotspot process :
第一個看到的就是當(dāng)前進(jìn)程中的線程:
到這里,我們的準(zhǔn)備工作就已經(jīng)結(jié)束,接著我們使用 Tools > Class Browser 找到對象 B 的內(nèi)存地址:
圖中紅框框起來的是我自己寫的三個類,可以看到我這里 B 的內(nèi)存地址是 0x00000007c0060c18
。
接下來,使用 Tools > Inspector 查看這個對象的詳細(xì)信息:
vtable 是虛表方法,這里我們看到 class B 有 7 個虛表方法,因?yàn)樗械膶ο蠖祭^承自 Object ,所以 B 繼承了 Object 的 5 個方法,然后還繼承了 A 的一個方法,自己重寫了一個方法,總共是 7 個方法。
這個我們可以進(jìn)行一下驗(yàn)證,可以在 Windows > Console 中使用 mem 命令進(jìn)行查看。
那么我們可以開始計算, vtable 是在 instanceKlass 對象實(shí)例的尾部,而 instanceKlass 大小在 64 位系統(tǒng)的大小為 0x1B8 ,因此 vtable 的起始地址等于 instanceKlass 的內(nèi)存首地址加上 0x1B8 等于 7C0060DD0 。
接下來,我們在 Windows > Console 中使用 mem 命令進(jìn)行驗(yàn)證:
第一列是方法實(shí)際在堆中的內(nèi)存地址,第二列則是內(nèi)存指針地址,我們可以將拿到的內(nèi)存指針地址去 A , B 和 Object 中分別查看,可以看到前 5 行對應(yīng)的是 Object 的方法,第 6 行對應(yīng)的是 A 對象中的方法,第 7 行則對應(yīng) B 對象中的方法。
3. JConsole
JConsole(Java Monitoring and Management Console) 是一款基于 JMX(Java Manage-ment Extensions) 的可視化監(jiān)視、管理工具。它的主要功能是通過 JMX 的 MBean(Managed Bean) 對系統(tǒng)進(jìn)行信息收集和參數(shù)動態(tài)調(diào)整。
JConsole 位于 JDK/bin 這個目錄下,直接雙擊 jconsole.exe 就可以直接啟動,在啟動之后,會自動搜索出當(dāng)前在本機(jī)運(yùn)行的所有虛擬機(jī)進(jìn)程。
這里可以看到我本機(jī)目前運(yùn)行了一個 JConsole ,一個 idea ,還有一個啟動的 tomcat 的源碼。
隨便雙擊一個服務(wù),進(jìn)入主頁面:
可以看到主界面里共包括概述、內(nèi)存、線程、類、 VM 摘要、 MBean 六個頁簽。
還是來個小示例,我們來了解下它的監(jiān)控功能。
public class MonitoringTest { // 內(nèi)存占位對象,一個對象大約 64KB static class OOMObject { public byte[] placeholder = new byte[64 * 1024]; } public static void fillHeap(int nums) throws InterruptedException { List<OOMObject> list = new ArrayList<>(); for (int i = 0; i < nums; i++) { Thread.sleep(50); list.add(new OOMObject()); } System.gc(); } public static void main(String[] args) throws InterruptedException { fillHeap(1000); } }
這個案例是使用大約 64KB/50ms 的速度向 Java 堆中填充數(shù)據(jù),一共填充 1000 次。
程序執(zhí)行后可以看到,在整個 Java 堆中,曲線一直是平滑向上的。
切換到內(nèi)存標(biāo)簽頁,查看 Eden 后可以發(fā)現(xiàn),整個 Eden 的圖形是一個折線:
再切換到 Gen ,可以看到整個老年代也是折疊向上的:
我們已經(jīng)在代碼里加了 System.gc()
,為什么看起來沒生效呢?
因?yàn)?System.gc()
是在 fillHeap()
方法中的,在 GC 的時候,還在作用域中,想要正?;厥绽夏甏?,需要將 System.gc()
這段代碼轉(zhuǎn)移到 fillHeap()
外面。
先修改下代碼:
public static void main(String[] args) throws InterruptedException { fillHeap(1000); System.gc(); // GC 后停頓 3s ,方便觀察圖像 Thread.sleep(3000); }
可以看到在最后進(jìn)程結(jié)束的時候, Gen 的柱狀圖已經(jīng)沒有內(nèi)存占用了,內(nèi)存回收成功。
3. VisualVM
VisualVM(All-in-One Java Troubleshooting Tool)是功能最強(qiáng)大的運(yùn)行監(jiān)視和故障處理程序之一,曾經(jīng)在很長一段時間內(nèi)是 Oracle 官方主力發(fā)展的虛擬機(jī)故障處理工具。
VisualVM 同樣在 JDK/bin 這個目錄下,雙擊 jvisualvm.exe 即可運(yùn)行。在啟動之后,直接在左側(cè)會顯示當(dāng)前在本機(jī)運(yùn)行的所有虛擬機(jī)進(jìn)程。
VisualVM 基于 NetBeans 平臺開發(fā)工具,所以一開始它就具備了通過插件擴(kuò)展功能的能力,有了插件擴(kuò)展支持, VisualVM 可以做到:
VisualVM 的插件可以在 工具->插件 中聯(lián)網(wǎng)后直接安裝。
我這里只安裝了兩個最常用的,一個是 GC 監(jiān)控的插件,還有一個可以動態(tài)插入調(diào)試程序的插件。
我這里使用最常用的開發(fā)工具 IDEA 啟動過程演示一下通過 VisualVM 監(jiān)控程序 GC 。
首先我們啟動 IDEA ,直到 IDEA 可以正常操作,看下 VisualVM 的 GC 監(jiān)控。
在主信息面板,可以看到 IDEA 所使用 JVM 的版本信息,可以看到具體的 JAVA_HOME 路徑,還可以看到具體的 JVM 參數(shù),這里可以看到 IDEA 啟動時設(shè)置的默認(rèn)最小堆和最大堆內(nèi)存的設(shè)置分別是 128MB 和 750 MB ,所使用的垃圾回收器則是 CMS 收集器。
然后點(diǎn)擊 Visual GC,可以看到:
在啟動過程中, Class 加載消耗了 28s 左右,而 Class 編譯則消耗了 35s 。并且在這個過程中, Minor GC 被觸發(fā)了 149 次,消耗只有 713ms ,我們更加關(guān)注的 Full GC 更是一次都沒有觸發(fā),消耗為 0 。
因?yàn)?IDEA 默認(rèn)使用的是 CMS 收集器,如果我們換成 G1 收集器會不會更快一些呢?
首先,找到 IDEA 的配置文件,我的 IDEA 是通過 Toolbox 進(jìn)行安裝的,所以我的 IDEA 的配置文件的路徑有點(diǎn)奇怪 D:\Program Files\JetBrains\apps\IDEA-U\ch-0\202.7660.26.vmoptions
。
先把這個文件備份到桌面一個,防止改壞了導(dǎo)致 IDEA 不能使用。
刪掉現(xiàn)有的垃圾回收器配置 -XX:+UseConcMarkSweepGC
,增加 G1 收集器的配置:
-XX:+UseG1GC
其余的配置不做修改,直接關(guān)閉 IDEA 重啟,再看下 GC 情況。
首先先看下主面板,看下我們的 GC 收集器是否已經(jīng)切換成功:
然后再看下 GC 面板:
Minor GC 竟然被觸發(fā)了 271 次,而且消耗達(dá)到了 853ms ,好吧,看來在客戶端還是更適合使用 CMS 做為垃圾回收器。
我們再修改下 -Xmx 這個配置,將配置的大小縮減為現(xiàn)在的一半,再把 GC 換回原有的 CMS ,看下 Full GC 的情況:
可以看到, Full GC 整整發(fā)生了 46 次,并且耗時超過了 21s ,而且這是 IDEA 的界面上也開始彈出警告,警告我們內(nèi)存不足了,需要調(diào)整。
嚇得我趕緊改回了原有配置,順便把 -Xmx 的大小加到了 1024 ,盡量減少 Full GC 的情況。
4. Java Mission Control
JMC 同樣在 JDK/bin 這個目錄下,雙擊 jmc.exe 即可運(yùn)行。
打開后在 JVM 瀏覽器面板中有兩個選項(xiàng),一個是 MBean ,一個是 JFR 飛行記錄器。
關(guān)于 MBean 這部分?jǐn)?shù)據(jù),與 JConsole 和 VisualVM 上取到的內(nèi)容是一樣的,只是展示形式上有些差別,就不多說了。
雙擊「飛行記錄器」,將會出現(xiàn)「飛行記錄器」窗口(如果第一次使用,還會收到解鎖商業(yè)功能的警告窗)。
注意:在使用前需要在 JVM 中增加如下兩個參數(shù),含義是解鎖 JFR 功能的鎖定。
-XX:+UnlockCommercialFeatures -XX:+FlightRecorder
飛行記錄報告里包含以下幾類信息:
5. 小結(jié)
這 4 款可視化工具看下來,個人感覺還是最后一個 JMC 對使用者來講最友好, MBean 數(shù)據(jù)源展示了大量的當(dāng)前 JVM 的信息,而且全都以圖表的形式進(jìn)行了展現(xiàn),更加給力還是它的 JFR 功能,可以記錄一段時間內(nèi)所有的操作,并且以圖表的形式進(jìn)行展現(xiàn),對我們分析問題時候的幫助無疑是巨大的。
當(dāng)然,喜歡用哪款工具完全是個人喜好,比如 VisualVM 也很強(qiáng)大,可能它本身的功能沒那么強(qiáng),但是它可以安裝插件,完全根據(jù)需要進(jìn)行插件的安裝,這個玩法非常 DIY ,總的算下來,我還是喜歡使用 VisualVM 更多一些。
關(guān)于帶你了解可視化JVM 故障處理工具就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學(xué)到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。