一文詳解JDK監控和故障處理命令及常見故障分析

JVM 的定位系統問題時,知識和經驗是關鍵基礎,數據是依據、工具是運用知識處理數據的手段

數據包括:運行日誌、異常堆棧、GC日誌、線程快照(thread dump、javacore文件)、堆轉儲快照(headdump / hprof 文件)html

1、調優命令

JDK監控和故障處理命令,在bin目錄下有:jps、 jstat、jmap、jhat、jstack、jinfojava

  • jps:顯示虛擬機進程,經常使用如:jps -l -vweb

  • jstat:收集虛擬機各方面的運行數據,經常使用如:jps-gcutil 276四、jstat -gc 2764 250 20數據庫

  • jinfo:顯示虛擬機配置信息數組

  • jmap:生成虛擬機內存轉儲快照(headdump 文件),經常使用如:jmap -dump:live,format=b,file=dump.hprof 28920瀏覽器

  • jhat:用於分析headdump 文件,他會創建一個http/html 的服務器,讓客戶能夠在瀏覽器上查看分析結果,經常使用如:jhat dump.hprof jstack: 顯示虛擬機線程快照,經常使用如:jstack -l 11494 下面作一 一介紹bash

2、Jps

顯示指定系統內全部的HotSpot虛擬機進程,服務器

格式 :多線程

jps - [hostid]
複製代碼

options 參數:函數

-q:只輸出LVMID,省略主類的名稱
  -m:輸出新建啓動時傳遞給主類main()函數的參數
  -l:輸出主類的全名,若是進程執行的是Jar包,輸出Jar路徑
  -v:輸出虛擬機進程啓動時JVM參數
複製代碼

其中[option]、[hostid]參數也能夠不寫

通常使用:

jps -l -m
複製代碼

3、Jstat

用於監視虛擬機運行時狀態信息的命令,它能夠顯示出虛擬機進程中的類裝載、內存、垃圾收集、JIT編譯等運行數據。

格式

jstat - [-t] [-h] [ []]
複製代碼
  • vmid: 進程號,interval 和count :表示查詢間隔和次數
  • options 參數以下
-class:監視類裝載、卸載熟練、總空間以及類裝載所消耗的時間
-gc : 監視堆情況,包括Eden區、兩個survivor區、老年代、永久代等容量、已用空間和GC 時間合計等信息
-gccapacity:監視內容和 -gc基本相同,但輸出主要關注堆各個區域使用到最大,最小空間
-gcutil:監視內容和 -gc基本相同,但輸出主要關注已使用空間佔總空間的百分比
-gccause:與 -gcutil同樣,額外輸出致使上次GC產生的緣由
-gcnew:監視新生代GC情況
-gcnewcapacity:監視內容和 -gcnew 基本相同,輸出輸出主要關注使用到的最大、最小空間
-gcold:監視老年代GC情況
-gcoldcapacity:監視內容和 -gcold 基本相同,輸出輸出主要關注使用到的最大、最小空間
-gcpermcapacity:輸出永久代使用的最大、最小空間
-compiler:輸出JIT 編譯期編譯過的方法、耗時等信息
-printcompilation:輸出已經被JIT編譯的方法
複製代碼

通常使用:

jps-gcutil 2764 //輸出的是已使用空間佔總空間的百分比

jstat -gc 2764 250 20 //每隔250ms輸出2764的gc狀況,一共輸出20次

4、Jinfo

做用是實時查看和調整虛擬機運行參數。 以前的jps -v口令只能查看到顯示指定的參數,若是想要查看未被顯示指定的參數的值就要使用jinfo口令

格式

jinfo [option vmid]
複製代碼

vmid: 進程號

option參數

-flag : 輸出指定args參數的值
-flags : 不須要args參數,輸出全部JVM參數的值
-sysprops : 輸出系統屬性,等同於System.getProperties()
複製代碼

通常使用:jinfo -flag 11494

5、Jmap

用於生成heap dump文件,若是不使用這個命令,還闊以使用-XX:+HeapDumpOnOutOfMemoryError參數來讓虛擬機出現OOM的時候·自動生成dump文件(阿里開發手冊推薦)。說明:OOM 的發生是有機率的,甚至相隔數月纔出現一例,出錯時的堆內信息對解決問題很是有幫助。

jmap不只能生成dump文件,還闊以查詢finalize執行隊列、Java堆和永久代的詳細信息,如當前使用率、當前使用的是哪一種收集器等。

格式

jmap - [vmid]
複製代碼

option 參數

-dump : 生成堆轉儲快照
-finalizerinfo : 顯示在F-Queue隊列等待Finalizer線程執行finalizer方法的對象
-heap : 顯示Java堆詳細信息
-histo : 顯示堆中對象的統計信息
-permstat : to print permanent generation statistics
-F : 當-dump沒有響應時,強制生成dump快照
複製代碼

通常使用 :

jmap -dump:live,format=b,file=dump.hprof 28920

dump堆到文件,format指定輸出格式,live指明是活着的對象,file指定文件名

dump.hprof這個後綴是爲了後續能夠直接用MAT(Memory Anlysis Tool)打開。

6、Jhat

用來分析jmap生成的dump;與jmap搭配使用;jhat內置了一個微型的HTTP/HTML服務器,生成dump的分析結果後,能夠在瀏覽器中查看。

在此要注意,通常不會直接在服務器上進行分析,由於jhat是一個耗時而且耗費硬件資源的過程,通常把服務器生成的dump文件複製到本地或其餘機器上進行分析。

格式

jhat [dumpfile]
複製代碼

7、Jstack

用於生成java虛擬機當前時刻的線程快照。線程快照是當前java虛擬機內每一條線程正在執行的方法堆棧的集合,生成線程快照的主要目的是定位線程出現長時間停頓的緣由,如線程間死鎖、死循環、請求外部資源致使的長時間等待等。 若是java程序崩潰生成core文件,jstack工具能夠用來得到core文件的java stack和native stack的信息,從而能夠輕鬆地知道java程序是如何崩潰和在程序何處發生問題。另外,jstack工具還能夠附屬到正在運行的java程序中,看到當時運行的java程序的java stack和native stack的信息, 若是如今運行的java程序呈現hung的狀態,jstack是很是有用的。

格式

jstack [option] LVMID
複製代碼

option參數

-F : 當正常輸出請求不被響應時,強制輸出線程堆棧
-l : 除堆棧外,顯示關於鎖的附加信息
-m : 若是調用到本地方法的話,能夠顯示C/C++的堆棧
複製代碼

通常使用:

jstack -l 11494
複製代碼

8、調優工具

1. jconsole
  • jdk /bin 目錄下,單機jconsole.exe 啓動啓動
  • 自動搜索本機運行的全部虛擬機進程,不須要用戶本身在使用jps 來查詢

GChisto是一款專業分析gc日誌的工具,能夠經過gc日誌來分析:Minor GC、full gc的時間、頻率等等,經過列表、報表、圖表等不一樣的形式來反應gc的狀況。

GC Easy:推薦此工具進行gc分析;這是一個web工具,在線使用很是方便,進入官網,講打包好的zip或者gz爲後綴的壓縮包上傳,過一會就會拿到分析結果。

2. VisualVM

jdk 集成的分析工具,在jdk /bin 目錄下,單機jvisualvm.exe 啓動

3. Oracle Java Mission Control

jdk 集成的分析工具,在jdk /bin 目錄下,單機jmc.exe 啓動

9、常見問題分析

1. 查找CPU飆升的緣由

問題分析步驟:

  • 首先,須要知道哪一個進程佔用CPU比較高,
  • 其次,須要知道佔用CPU高的那個進程中的哪些線程佔用CPU比較高,
  • 而後,須要知道這些線程的stack trace。 問題解決步驟:

①. top和pgrep來查看系統中Java進程的CPU佔用狀況。

  • 命令以下:top -p pgrep -d , java

  • pgrep:進程號,top -p:進程的信息。記錄下CPU佔用率最高的那個進程號。 ②. top來查看進程中CPU佔用最高的那些線程

  • top -Hp 12345 假定12345爲佔用CPU高的進程號。-H是顯示該進程中線程的CPU佔用狀況。一樣,記錄下CPU佔用率高的那些線程號。 ③. ctrl+H 切換到線程模式,找到佔用cpu最高的線程。並把線程號轉化爲十六進制,printf "%x\n" <線程ID>

④. 經過jstack導出Java應用中線程的stack trace(堆棧軌跡)

jstack 12345 注意:由於top中顯示的線程號是10進制,jstack的輸出結果中的線程號是16進制,因此只須要把top中看到線程號轉換成16進制

小結一下,咱們經過top和jstack來找到CPU佔用高的線程的stack trace,可使用Eclipse Memory Analyzer插件分析

2. Java堆溢出和泄漏

①. 內存溢出

程序在申請內存時,沒有足夠的內存空間供其使用

危害:容易受攻擊 影響因素以下幾大類:

  • 內存中加載的數據量過於龐大,如一次從數據庫取出過多數據
  • 集合類中有對對象的引用,使用完後未清空,使得JVM不能回收
  • 代碼中存在死循環或循環產生過多重複的對象實體

解決方案:

  • 修改JVM啓動參數,直接增長內存
  • 檢查錯誤日誌,是否有其餘異常或錯誤;
  • 對代碼進行走查和分析,找出可能發生內存溢出的位置
  • 重點排查:數據庫的取值,死循環和遞歸調用

②. 內存泄漏

沒法釋放已申請的內存空間

危害:頻繁GC、運行崩潰 影響因素以下幾大類:

  • 靜態集合類引發內存泄露
  • 當集合裏面的對象屬性被修改後,再調用remove()方法時不起做用。
Set<Person> set = new HashSet<Person>();
Person p3 = new Person("唐僧","pwd1",25);
p3.setAge(2); //修改p3的年齡,此時p3元素對應的hashcode值發生改變
set.remove(p3); //此時remove不掉,形成內存泄漏
複製代碼
  • 監聽器。釋放對象時沒有刪除監聽器。
  • 各類鏈接 ,好比數據庫鏈接
  • 單例對象持有外部對象的引用 解決辦法:使用工具jconsole分析

堆的最小值-Xms參數,最大值-Xmx參數

//代碼實現堆溢出:---> 無限循環建立 對象
List list =new ArrayList();
int i=0;
while(true){
    list.add(new byte[5*1024*1024]);//----------->就是這一步
    System.out.println("分配次數:"+(++i))
}
複製代碼

③. Java棧溢出

棧溢出SOF定義:線程請求的棧深度超過虛擬機容許的最大深度

  • 不管是因爲棧幀太大仍是棧容量過小,當內存沒法分配時都是OOM異常。
  • 虛擬機棧溢出:深度溢出:遞歸方法;廣度溢出:大數組,創建多線程
//代碼實現棧泄漏---> 方法無限遞歸調用
public void add(int i){
    add(i+1);
}
複製代碼

前期我也和不少小夥伴同樣,處處收集了不少資料,後面發現不少重複的!下面都是本身整理好的!如今BAT夢想成真,我就把資料貢獻出來給有須要的人!

順便求一波關注,哈哈~各位小夥伴關注我後私信【Java】就能夠免費領取

原文出處: www.jianshu.com/p/5bbac07c6…
相關文章
相關標籤/搜索