通過前面的幾篇博客,我們介紹了Java虛擬機的內存分配以及內存回收等理論知識,了解這些知識對於我們在實際生產環境中提高系統的運行效率是有很大的幫助的。但是話又說回來,在實際生產環境中,線上項目正在運行,我們怎么去監控虛擬機運行效率?又或者線上項目發生了OOM,異常堆棧信息,我們又怎么去抓取,然后怎么去分析定位問題呢?
本篇博客,我們就來介紹各種虛擬機監控和分析工具,當然都是命令行工具,不夠直觀,下篇博客我們會介紹各種可視化工具。
1、jps:顯示虛擬機進程
JVM Process Status Tools ,顯示指定系統內所有的 HotSpot 虛擬機進程。
該命令有如下常用參數:
①、-l
顯示應用程序main類的完整包名稱或應用程序的JAR文件的完整路徑名。
②、-v
顯示虛擬機啟動時的JVM參數。
③、-m
顯示虛擬機進程啟動時傳遞給主類 main() 函數的參數。
比如,我在服務器上啟動了一個Tomcat,如下:
然后,輸入 jps 命令,打印信息如下:
這里的 Bootstrap 便是啟動的 Tomcat進程。可以加上 -v 參數,顯示所有傳遞給 JVM的參數信息。
PS:jps 命令默認是沒有安裝的,需要進行安裝,具體安裝步驟可以百度,我這里就不做詳細介紹了。
jps更多詳細信息,請參考官方文檔:https://docs.oracle.com/javase/8/docs/technotes/tools/unix/jps.html
2、jstat:統計監視虛擬機信息工具
JVM Statistics Monitoring Tool,用於收集虛擬機各方面的運行數據。
jstat 是用於監視虛擬機各種運行時狀態信息的命令行工具。它可以顯示本地或遠程虛擬機進程中的類裝載、內存、垃圾收集、JIT編譯等運行時數據,它是運行時期定位虛擬機性能問題的首選工具。但是終究只是命令行工具,后面我們會介紹圖形化工具,更加直觀。
該命令監控本地的格式如下:
jstat -參數 vmid 采樣間隔時間 采樣次數
①、常用參數有如下
②、vmid
表示目標虛擬機的標識符,在Linux系統上可以通過上小節我們介紹的 jps 命令,前面輸出的數字便是進程 PID。在windows平台上,可以通過任務管理器查看。
③、采樣間隔時間
默認單位是毫毛,必須是正整數。
實例1:這里我們加入 -class 參數,查看類裝載信息:
相關表頭信息:
Loaded:加載的類數量。
Bytes:加載的類字節KB大小。
Unloaded:卸載的類數量。
Bytes:卸載的類字節KB大小。
Time:執行類加載和卸載操作所花費的時間。
jstat更多詳細信息,請參考官方文檔:https://docs.oracle.com/javase/8/docs/technotes/tools/unix/jstat.html
3、jinfo:實時的查看和調整虛擬機各項參數
jinfo(Confiiguration Info for Java):實時的查看和調整虛擬機各項參數
jinfo ,通過此命令,我們可以實時的查看和調整虛擬機的各項參數(包括顯示指定或默認配置的)。
該命令格式如下:
jinfo [ 選項 ] pid
①、常用選項如下
一、沒有選項
打印系統屬性名稱鍵值對。
二、-參數名稱
打印指定參數的名稱和值。
三、-flag [+|-] 參數名稱
啟用或者禁用指定的布爾命令。
四、-flag name=value
設置參數name的值為value
五、-sysprops
打印Java屬性名稱鍵值對。
②、pid
進程號,和上面一樣,可以通過jps命令獲取。
jinfo更多詳細信息,請參考官方文檔:https://docs.oracle.com/javase/8/docs/technotes/tools/unix/jinfo.html
4、jmap:內存映像工具
jmap(Memory Map for Java):用於生成堆存儲快照
jmap主要用於獲取堆存儲快照文件,在生產環境中,發生OOM(堆內存溢出)異常時,我們可以通過這個快照文件來快速定位到具體代碼位置。
這個命令還可以查詢 finalize 隊列,Java堆和永久代信息,如空間使用率、當前用的是哪種垃圾收集器等。
該命令格式如下:
jmap [參數] pid
①、常用參數如下:
對於堆內存溢出異常,在前面介紹虛擬機參數時,我們介紹過,通過下面兩個參數,也能夠打印堆內存快照。
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath
下面,我們通過如下代碼,演示堆內存溢出異常:
1 package com.ys.algorithmproject.leetcode.demo.JVM; 2 3 import java.util.ArrayList; 4 import java.util.List; 5 6 /** 7 * Create by YSOcean 8 * 9 */ 10 public class JmapTest { 11 private static final int _1MB = 1024*1024; 12 13 /** 14 * 虛擬機參數設置: -Xms20M -Xmx20M -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./ 15 * @param args 16 */ 17 public static void main(String[] args) { 18 List<Object> list = new ArrayList<>(); 19 while(true){ 20 list.add(new Object[_1MB]); 21 } 22 } 23 }
設置虛擬機參數后,然后運行這段代碼,就會發生堆內存溢出異常,並在根目錄下生成快照文件 java_pid10840.hprof。
那么,怎么通過 jmap 命令來生成堆內存快照呢?
jmap -dump:format=b,file=heap20190821.hprof 16823
后面的數字是進程PID,可以通過jps命令來獲取。
得到堆內存快照了,那么我們怎么去查看呢?
在eclipse中,可以下載 MAT 工具,而在 IDEA中,可以下載 JProfiler 插件。實在不行,可以用我們下篇博客介紹的幾個可視化工具,具體情況見下篇博客。
jmap更多詳細信息,請參考官方文檔:https://docs.oracle.com/javase/8/docs/technotes/tools/unix/jmap.html
5、jstack:Java堆棧跟蹤工具
Stack Trace for Java,用於生成虛擬機當前時刻的線程快照。
線程快照其實就是當前虛擬機每一條線程正在執行的堆棧的集合,通過線程快照可以用來定位線程出現長時間停頓的原因(線程間死鎖、死循環、請求外部資源導致的長時間等待)。
該命令格式如下:
jstack [選項] pid
①、常用選項如下:
參考文檔:https://docs.oracle.com/javase/8/docs/technotes/tools/index.html