【JVM進階之路】九:性能監控工具-可視化工具篇


在前面已經學習了JVM性能監控的命令行工具,接下來學習JVM性能監控的命令行工具,通過可視化工具可以更直觀地監控JVM性能、處理JVM相關問題。

1、JConsole

JConsole( Java Monitoring and Management Console),是一款基於 JMX( Java Manage-ment Extensions) 的可視化監視管理工具。

它的功能主要是對系統進行收集和參數調整,不僅可以用在虛擬機本身的管理上,還可以用於運行於虛擬機之上的軟件中。

1.1、JConsole連接Java程序

JConsole程序位於%JAVA_HOME%bin目錄下,直接通過命令啟動。

JConsole啟動和連接

在新建連接對話框中,羅列了所有的本地Java應用程序,選擇需要連接的程序即可。

下面還有一個用於連接遠程進程的文本框,輸入正確的遠程地址即可連接。

如果一個程序需要使用JConsole與那成連接,則需要在啟動Java程序時,加上以下參數:

JAVA_OPTS="-Dfile.encoding=UTF-8" 
JAVA_OPTS="$JAVA_OPTS -Dlog.dir=$LOG_PATH" 
JAVA_OPTS="$JAVA_OPTS -Djava.rmi.server.hostname=xxx.xxx.xxx.xxx(本機IP) -Dcom.sun.management.jmxremote" 
JAVA_OPTS="$JAVA_OPTS -Dcom.sun.management.jmxremote.port=xx" 
JAVA_OPTS="$JAVA_OPTS -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.local.only=false"
JAVA_OPTS="$JAVA_OPTS -Dcom.sun.management.jmxremote.ssl=false"

1.2、Java程序概況

使用JConsole連接了一個本地程序,在概述可以看到Java程序運行的概覽信息,包括堆內存使用情況線程CPU使用情況四項信息的曲線圖。

JConsole概覽

1.3、內存監控

內存的作用相當於可視化的jstat命令,用於監視被收集器管理的虛擬機內存。

它不僅包含堆內存的整體信息,更細化到eden區、suvivior區、老年代的使用情況。

JConsole內存監控

為了更加清晰地查看內存地變化,運行下面一段程序,然后連接:

/**
 * VM參數: -Xms100m -Xmx100m -XX:+UseSerialGC
 */
public class JConcoleRAMMonitor {

    /***
     * 內存占位符對象,一個OOMObject大約占64KB
     */
    static class OOMObject {
        public byte[] placeholder = new byte[64 * 1024];
    }

    public static void fillHeap(int num) throws InterruptedException {
        List<OOMObject> list = new ArrayList<OOMObject>();
        for (int i = 0; i < num; i++) {
            // 稍作延時,令監視曲線的變化更加明顯
            Thread.sleep(300);
            list.add(new OOMObject());
        }
        System.gc();
    }

    public static void main(String[] args) throws Exception {
        fillHeap(2000);
    }
}

這段代碼的作用是以64KB/50ms的速度向Java堆中填充數據,一共填充1000次。

觀察Eden區的運行趨勢,發現呈折線。觀察堆內存使用,發現以稍有曲折的狀態向上增長。

Eden區內存變化狀況

執行System.gc()之后,老年代的柱狀圖仍然顯示峰值狀態,最后程序會以堆內存溢出結束,這是因為空間未能回收——List<OOMObject>list對象一直存活, fillHeap()方法仍然沒有退出,如果把 System.gc()移動到fillHeap()方法外調用就可以回收掉全部內存。

1.4、線程監控

JConcole還可以監控線程,相當於可視化的jstack命令。如圖,JConcole顯示了系統內的線程數量,並在屏幕下方顯示了程序中所有的線程。單擊線程名稱,就可以查看線程的棧信息。

JConsole線程監控

使用JConsole還可以快速定位死鎖問題。

這是一段會產生死鎖的代碼:

public class ThreadLockDemo {

    /**
     * 線程死鎖等待演示
     */
    static class SynAddRunalbe implements Runnable {
        int a, b;

        public SynAddRunalbe(int a, int b) {
            this.a = a;
            this.b = b;
        }

        @Override
        public void run() {
            synchronized (Integer.valueOf(a)) {
                synchronized (Integer.valueOf(b)) {
                    System.out.println(a + b);
                }
            }
        }
    }

    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
            new Thread(new SynAddRunalbe(1, 2)).start();
            new Thread(new SynAddRunalbe(2, 1)).start();
        }
    }
}

出現線程死鎖以后,點擊JConsole線程面板的檢測到死鎖按鈕,將會看到線程的死鎖信息。

線程死鎖檢測

可以看到線程Thread-199等待線程Thread-21持有的資源。

1.5、類加載情況

如圖,類頁面顯示了已經裝載的類數量。在詳細信息欄中,還顯示了已經卸載的類的數量。

類加載情況

1.6、虛擬機信息

VM摘要,JConsole顯示了當前應用程序的運行環境,包括虛擬機類型、版本、堆信息以及虛擬機參數等。

VM 摘要

2、VisualVM

VisualVM(All-in-One Java Troubleshooting Tool)是功能最強大的運行監視和故障處理程序之一,曾經在很長一段時間內是Oracle官方主力發展的虛擬機故障處理工具。

相比一些第三方工具,VisualVM有一個很大的優點:不需要被監視的程序基於特殊Agent去運行,因此它的通用性很強,對應用程序實際性能的影響也較小,使得它可以直接應用在生產環境中。

2.1、VisualVM安裝插件

在JDK6 Update7以后,VisualVM便作為JDK的一部分發布,它在%JAVA_HOME%bin 目錄下,點擊就可以啟動。

VisualVM位置

VisualVM的精華之處在於它的插件。插件安裝可以手動安裝或者自動安裝。

手動安裝,從地址 https://visualvm.github.io/pluginscenters.html 下載載nbm包,點擊“工具->插件->已下載”菜單,然后在彈出對話框中指定nbm包路徑便可完成安裝。

一般選擇自動安裝,點擊工具-> 插件菜單,在可用插件里可以看到可安裝的插件,按需安裝即可。

VisualVM安裝插件

VisualVM中概述,監視線程MBeans的功能與前面介紹的JConsole差別不大,這里就不在贅言。

2.2、生成、瀏覽堆轉儲快照

在VisualVM中生成堆轉儲快照文件有兩種方式,可以執行下列任一操作:

  • 應用程序窗口中右鍵單擊應用程序節點,然后選擇堆Dump
  • 應用程序窗口中雙擊應用程序節點以打開應用程序標簽,然后在“監視”標簽中單擊堆Dump

堆Dump

生成堆轉儲快照文件之后,該堆的應用程序下增加了一個以[heap-dump]開頭的子節點。如果需要把堆轉儲快照保存或發送出去,就需要heapdump節點上右鍵選擇“另存為”菜單,否則當VisualVM關閉時,生成的堆轉儲快照文件會被當作臨時文件自動清理掉。要打開一個由已經存在的堆轉儲快照文件,通過文件菜單中的“裝入”功能,選擇磁盤上的文件即可。

VisualVM生成的堆轉儲快照

2.3、分析程序性能

要開始性能分析,先選擇“CPU”和“內存”按鈕中的一個,然后切換到應用程序中對程序進行操作,VisualVM會記錄這段時間中應用程序執行過的所有方法。

VisualVM性能分析

如果是進行處理器執行時間分析,將會統計每個方法的執行次數、執行耗時;

VisualVM CPU分析

如果是內存分析,則會統計每個方法關聯的對象數以及這些對象所占的空間。

VisualVM內存分析

等要分析的操作執行結束后,點擊“停止”按鈕結束監控過程。

2.4、BTrace動態日志跟蹤

BTrace是個很有意思的插件,它可以在不停機的情況下,通過字節碼注入動態監控系統的運行情況。

Btrace自動安裝如下,到github的網絡可能存在不穩定的問題,可以重試,或者手動安裝

BTrace插件安裝

在VisualVM中安裝了BTrace插件后,在應用程序面板中右擊要調試的程序,會出現“Trace Application…”菜單:

image-20210407231817248

點擊將進入BTrace面板。這個面板看起來就像一個簡單的Java程序開發環境:

image-20210407231851293

現在來嘗試使用BTrace追蹤正在運行的程序。

一段簡單的Java代碼:產生兩個1000以內的隨機整數,輸出這兩個數字相加的結果。

public class BTraceTest {
    public int add(int a, int b) {
        return a + b;
    }

    public static void main(String[] args) throws IOException {
        BTraceTest test = new BTraceTest();
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        for (int i = 0; i < 10; i++) {
            reader.readLine();
            int a = (int) Math.round(Math.random() * 1000);
            int b = (int) Math.round(Math.random() * 1000);
            System.out.println(test.add(a, b));
        }
    }
}

運行程序,現在需要在不停止程序的情況下,監控程序中生成的兩個隨機數。在VisualVM中打開該程序的監視,在BTrace頁 簽填充TracingScript的內容,輸入調試代碼:

/* BTrace Script Template */
import com.sun.btrace.annotations.*;
import static com.sun.btrace.BTraceUtils.*;

@BTrace
public class TracingScript {
	 @OnMethod(clazz = "cn.fighter3.test.BTraceTest", 
      method = "add", 
      location = @Location(Kind.RETURN)
    )
    public static void func(@Self cn.fighter3.test.BTraceTest instance, 
        int a, int b,
        @Return int result) {
        println("調用堆棧:");
        jstack();
        println(strcat("方法參數A:", str(a)));
        println(strcat("方法參數B:", str(b)));
        println(strcat("方法結果:", str(result)));
    }
}

點擊start按鈕,當程序運行時將會在Output面板輸出調試信息:

image-20210407233504006

BTrace的用途很廣泛,打印調用堆棧、參數、返回值只是它最基礎的使用形式,更多應用可以查看官方倉庫 https://github.com/btraceio/btrace/wiki

3、Java Mission Control

JMV最初是JRockit虛擬機提供的一款診斷工具。在Oracle JDK7 Update 40以后,它就綁定在Oracle JDK中發布。

JMC位置是%JAVA_HOME%/bin/jmc.exe,打開軟件界面:

JMC主要界面

在左側的“JVM瀏覽器”面板中自動顯示了通過JDP協議(Java Discovery Protocol)找到的本機正在運行的HotSpot虛擬機進程。

3.1、MBean服務器

點擊本地進程的MBean服務器

MBean服務器

可以看到,以飛行儀表的視圖顯示了Java堆使用率,CPU使用率和Live Set+Fragmentation。

3.2、飛行記錄器(Flight Recorder)

飛行記錄器是JMC提供的另一大功能,它通過記錄程序在一段時間內的運行情況,將記錄結果進行分析和展示,可以更進一步對系統的性能進行分析和診斷。

要使用JFR,程序啟動需要帶以下參數:

-XX:+UnlockCommercialFeatures  -XX:+FlightRecorder

連接加了相關參數啟動的程序,啟動飛行記錄,進行一分鍾的性能記錄:

image-20210408000854241

記錄結束后,JMC會自動打開剛才的記錄:

image-20210408001133160

JFR提供的數據質量通常也要比其他工具通過代理形式采樣獲得或者從MBean中取得的數據高得多。以垃圾搜集為例,HotSpot的MBean中一般有各個分代大小、收集次數、時間、占用率等數據(根據收集器不同有所差別),這些都屬於“結果”類的信息,而JFR中還可以看到內存中這段時間分配了哪些對象、哪些在TLAB中(或外部)分配、分配速率 和壓力大小如何、分配歸屬的線程、收集時對象分代晉升的情況等。

4、第三方工具

以上三個都是JDK自帶的性能監控工具,除此之外還有一些第三方的性能監控工具。

  • MAT

Java 堆內存分析工具。

  • GChisto

GC 日志分析工具。

  • GCViewer

GC 日志分析工具。

  • JProfiler

商用的性能分析利器。

  • arthas

阿里開源診斷工具。

  • async-profiler

Java 應用性能分析工具,開源、火焰圖、跨平台。

這里只是簡單羅列,就不再展開詳細介紹。




參考:

【1】:周志明編著《深入理解Java虛擬機:JVM高級特性與最佳實踐》

【2】:《實戰JAVA虛擬機 JVM故障診斷與性能優化》

【3】:Jvm 系列(七):Jvm 調優-工具篇

【4】:給,你們想要的排查問題的可視化工具


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM