1. 程式人生 > 其它 >JDK 內建實用工具:監視、故障排除

JDK 內建實用工具:監視、故障排除

監視工具

JConsole

JConsole 圖形使用者介面是一種符合 Java 管理擴充套件 (JMX) 規範的監視工具。JConsole 使用 Java 虛擬機器 (Java VM) 的廣泛檢測來提供有關在 Java 平臺上執行的應用程式的效能和資源消耗的資訊。

使用方法

本地
  • 使用jconsole命令:監視本地執行的所有 Java 應用程式,JConsole 可以連線到這些應用程式。

  • 使用jconsole PID命令:監視指定PID的Java應用程式。

獲取java PID的方法:通過工作管理員檢視、通過Java提供的jps命令檢視。

遠端

使用jsconsole hostName:portNum

命令:hostName是執行應用程式的系統的名稱,portNum是您在啟動 Java VM 時啟用 JMX 代理時指定的埠號。

使用service:jmx:<protocol>:<sap>命令:使用 JMX 服務 URL 進行連線。

內容分析

將 JConsole 連線到應用程式後,JConsole 由六個選項卡組成。

  • 概述:顯示有關 Java VM 和受監視值的概述資訊。

  • 記憶體:顯示有關記憶體使用的資訊。

  • 執行緒:顯示有關執行緒使用的資訊。

  • 類:顯示有關類載入的資訊。

  • VM:顯示有關 Java VM 的資訊。

  • MBeans:顯示有關 MBeans 的資訊。

組成部分

概覽

顯示有關 CPU 使用情況、記憶體使用情況、執行緒計數和在 Java VM 中載入的類的圖形監視資訊。

提供執行GC的操作,可以隨時點選按鈕進行垃圾回收

  • 伊甸園空間(堆): 最初為大多數物件分配記憶體的池。

  • 倖存者空間(堆): 包含在伊甸園空間垃圾回收中倖存下來的物體的池。

  • 終身代(堆): 包含在倖存者空間中存在一段時間的物件的池。

  • 永久生成(非堆): 包含虛擬機器本身的所有反射資料的池,如類和方法物件。使用類資料共享的 Java VM,這一代分為只讀和讀寫區域。

  • 程式碼快取(非堆): HotSpotJava VM 還包括一個程式碼快取,其中包含用於編譯和儲存本機程式碼的記憶體。

堆和非堆記憶體

Java VM 管理兩種型別的記憶體:堆記憶體和非堆記憶體,這兩種記憶體都是在 Java VM 啟動時建立的。

  • 堆記憶體是 Java VM 為所有類例項和陣列分配記憶體的執行時資料區域。堆的大小可能是固定的或可變的。垃圾回收器是一個自動記憶體管理系統,用於回收物件的堆記憶體。

  • 非堆記憶體包括所有執行緒之間共享的方法區域和 Java VM 的內部處理或優化所需的記憶體。它儲存每類結構,如執行時常量池、欄位和方法資料,以及方法和建構函式的程式碼。方法區域在邏輯上是堆的一部分,但是,根據實現,Java VM 可能不會對它進行垃圾回收或壓縮。與堆記憶體一樣,方法區域可能為固定大小或可變大小。方法區域的記憶體不需要連續。

記憶體池和記憶體管理器

記憶體池和記憶體管理器是 Java VM 記憶體系統的關鍵方面。

  • 記憶體池表示 Java VM 管理的記憶體區域。Java VM 至少有一個記憶體池,它可能會在執行期間建立或刪除記憶體池。記憶體池可以屬於堆記憶體或非堆記憶體。

  • 記憶體管理器管理一個或多個記憶體池。垃圾回收器是一種記憶體管理器,負責回收不可到達的物件使用的記憶體。Java VM 可能具有一個或多個記憶體管理器。它可以在執行期間新增或刪除記憶體管理器。記憶體池可以由多個記憶體管理器管理。

垃圾回收

垃圾回收 (GC) 是 Java VM 釋放不再引用的物件佔用的記憶體的方式。通常認為具有活動引用為"活動"且未引用(或無法訪問)物件的物件為"已死"。垃圾回收是釋放死物件使用的記憶體的過程。GC 使用的演算法和引數對效能有顯著影響。

Java hotspot VM 垃圾回收器使用代數 GC。生成 GC 利用大多數程式符合以下概括的觀察。

  • 它們建立許多壽命較短的物件,例如迭代器和區域性變數。

  • 它們建立一些壽命很長的物件,例如高階持久物件。

執行緒

提供有關執行緒使用的資訊。

  • 查詢監視器死鎖執行緒: 檢測物件監視器鎖上是否有任何執行緒死鎖。此操作返回死鎖執行緒指示的陣列。

  • getThreadInfo: 返回執行緒資訊。這包括執行緒當前被阻止的名稱、堆疊跟蹤和監視器鎖(如果有)以及持有該鎖的執行緒以及執行緒爭用統計資訊。

  • 獲取ThreadCpu時間: 返回給定執行緒消耗的 CPU 時間

顯示有關類載入的資訊。

VM 概要

提供有關 Java VM 的資訊。

 
MBean

以通用方式顯示有關在平臺 MBean 伺服器註冊的所有 MBeans 的資訊。MBeans 選項卡允許您訪問平臺 MXBean 檢測的完整集,包括在其他選項卡中不可見的儀器。此外,您還可以使用 MBeans 選項卡監視和管理應用程式的 MBeans。

jps

列出目標系統上已檢測的 Java 虛擬機器 (JVM)。

jstat

監視 Java 虛擬機器 (JVM) 統計資訊。

對Java應用程式的資源和效能進行實時的命令列的監控,包括了對Heap size和垃圾回收狀況的監控。

命令格式

jstat [-option] [PID]

option引數

  • class: 顯示有關類載入器行為的統計資訊。

  • compiler: 顯示有關 Java HotSpot VM 實時編譯器行為的統計資訊。

  • gc: 顯示有關垃圾回收堆行為的統計資訊。

  • gccapacity: 顯示有關幾代人容量及其相應空間的統計資訊。

  • gccause: 顯示有關垃圾回收統計資訊(與 相同)的摘要,以及最後和當前(如果適用)垃圾回收事件的原因。-gcutil

  • gcnew: 顯示新一代行為的統計資訊。

  • gcnewcapacity: 顯示有關新一代大小及其相應空間的統計資訊。

  • gcold: 顯示有關舊一代和元空間統計資訊行為的統計資訊。

  • gcoldcapacity: 顯示有關舊一代大小的統計資訊。

  • gcmetacapacity: 顯示有關元空間大小的統計資訊。

  • gcutil: 顯示有關垃圾回收統計資訊的摘要。

  • printcompilation: 顯示 Java 熱點 VM 編譯方法統計資訊。

1.jstat –class <pid> : 顯示載入class的數量,及所佔空間等資訊。

 2.jstat -compiler <pid>顯示VM實時編譯的數量等資訊。

 3.jstat -gc <pid>: 可以顯示gc的資訊,檢視gc的次數,及時間。

 4.jstat -gccapacity <pid>:可以顯示,VM記憶體中三代(young,old,perm)物件的使用和佔用大小

 5.jstat -gcutil <pid>:統計gc資訊

 6.jstat -gcnew <pid>:年輕代物件的資訊。

 7.jstat -gcnewcapacity<pid>: 年輕代物件的資訊及其佔用量。

 8.jstat -gcold <pid>:old代物件的資訊。

 9.jstat -gcoldcapacity <pid>: old代物件的資訊及其佔用量。

 10.jstat -gcpermcapacity<pid>: perm物件的資訊及其佔用量。

 11.jstat -printcompilation <pid>:當前VM執行的資訊。

jstatd

監視 Java 虛擬機器 (JVM),並使遠端監視工具能夠連線到 JVM

命令格式

jstatd -[option]

option

  • -nr 當找不到現有的RMI登錄檔時,不嘗試使用jstatd程序建立一個內部的RMI登錄檔。
  • -p port 在指定的埠查詢RMI登錄檔。如果沒有找到,並且沒有指定-nr選項,則在該埠自行建立一個內部的RMI登錄檔。
  • -n rminame RMI登錄檔中繫結的RMI遠端物件的名稱。預設的名稱為JStatRemoteHost。如果多個jstatd伺服器在同一主機上執行,你可以通過指定該選項來讓每個伺服器匯出的RMI物件具有唯一的名稱。不管如何,這樣做需要將唯一的伺服器名稱包含進監控客戶端的hostid和vmid字串中。
  • -Joption 將選項引數傳遞給被javac呼叫的java啟動程式。例如,-J-Xms48m設定啟動記憶體為48 MB。使用-J將選項引數傳遞給執行Java應用程式的底層虛擬機器,這是一種常見慣例。

使用方法

1.在jdk的bin目錄下建立檔案jstatd.all.policy

2.寫入下面的安全配置

grant codebase "file:/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.191.b12-1.el7_6.x86_64/lib/tools.jar" {
   permission java.security.AllPermission;
};
#此處寫絕對路徑,主要是防止路徑錯誤問題,排查問題,應該寫成相對路徑

3.啟動jstatd

./jstatd -J-Djava.security.policy=jstatd.all.policy -J-Djava.rmi.server.hostname=x.x.x.x &

4.使用jvisualvm工具遠端連線,進行監控

jvisualvm

VisualVM,能夠監控執行緒,記憶體情況,檢視方法的CPU時間和記憶體中的對 象,已被GC的物件,反向檢視分配的堆疊(如100個String物件分別由哪幾個物件分配出來的).

同時他還提供很多外掛可以自己安裝,是一款不錯的監控分析工具。

故障排除工具

JInfo

可以用來檢視正在執行的 java 應用程式的擴充套件引數,包括Java System屬性和JVM命令列引數;也可以動態的修改正在執行的 JVM 一些引數。當系統崩潰時,jinfo可以從core檔案裡面知道崩潰的Java應用程式的配置資訊

命令格式

引數說明

  • pid 對應jvm的程序id

  • executable core 產生core dump檔案

  • [server-id@]remote server IP or hostname 遠端的ip或者hostname,server-id標記服務的唯一性id

option

  • no option 輸出全部的引數和系統屬性

  • -flag name 輸出對應名稱的引數

  • -flag [+|-]name 開啟或者關閉對應名稱的引數

  • -flag name=value 設定對應名稱的引數

  • -flags 輸出全部的引數

  • -sysprops 輸出系統屬性

Javacore 概述

Javacore,也可以稱為“threaddump”或是“javadump”,它是 Java 提供的一種診斷特性,能夠提供一份可讀的當前執行的 JVM 中執行緒使用情況的快照。即在某個特定時刻,JVM 中有哪些執行緒在執行,每個執行緒執行到哪一個類,哪一個方法。應用程式如果出現不可恢復的錯誤或是記憶體洩露,就會自動觸發 Javacore 的生成。

使用方法

1.jinfo pid:輸出當前 jvm 程序的全部引數和系統屬性

 2.jinfo -flag name pid:輸出對應名稱的引數使用該命令,可以檢視指定的 jvm 引數的值。如:檢視當前 jvm 程序是否開啟列印 GC 日誌。

3.jinfo -flag [+|-]name pid:開啟或者關閉對應名稱的引數

使用 jinfo 可以在不重啟虛擬機器的情況下,可以動態的修改 jvm 的引數。尤其在線上的環境特別有用。

4.jinfo -flag name=value pid:修改指定引數的值。

注意:jinfo雖然可以在java程式執行時動態地修改虛擬機器引數,但並不是所有的引數都支援動態修改

5.jinfo -flags pid:輸出全部的引數

6.jinfo -sysprops pid:輸出當前 jvm 進行的全部的系統屬性

jhat

主要是用來分析java堆的命令,可以將堆中的物件以html的形式顯示出來,包括物件的數量,大小等等,並支援物件查詢語言。

1.使用jmap命令匯出堆檔案
jmap -dump:live,file=a.log pid

也可以使用下面方式匯出堆檔案

1、使用 jconsole 選項通過 HotSpotDiagnosticMXBean 從執行時獲得堆轉儲(生成dump檔案)、

2、虛擬機器啟動時如果指定了 -XX:+HeapDumpOnOutOfMemoryError 選項, 則在丟擲 OutOfMemoryError 時, 會自動執行堆轉儲。

3、使用 hprof 命令

2.使用jhat分析堆檔案
jhat -J-Xmx512M a1.log
3.檢視分析的html頁面

http://ip:7000/jhat中的OQL(物件查詢語言)

如果需要根據某些條件來過濾或查詢堆的物件,這是可能的,可以在jhat的html頁面中執行OQL,來查詢符合條件的物件

基本語法:

select <javascript expression to select>
[from [instanceof] <class name> <identifier>]
[where <javascript boolean expression to filter>]

解釋:

(1)class name是java類的完全限定名,如:java.lang.Stringjava.util.ArrayList, C是char陣列, java.io.Filejava.io.File[]

(2)類的完全限定名不足以唯一的辨識一個類,因為不同的ClassLoader載入的相同的類,它們在jvm中是不同型別的

(3)instanceof表示也查詢某一個類的子類,如果不明確instanceof,則只精確查詢class name指定的類

(4)from和where子句都是可選的

(5)java域表示:obj.field_name;java陣列表示:array[index]

舉例:

(1)查詢長度大於100的字串

select s from java.lang.String s where s.count > 100

(2)查詢長度大於256的陣列

select a from [I a where a.length > 256

(3)顯示匹配某一正則表示式的字串

select a.value.toString() from java.lang.String s where /java/(s.value.toString())

(4)顯示所有檔案物件的檔案路徑

select file.path.value.toString() from java.io.File file

(5)顯示所有ClassLoader的類名

select classof(cl).name from instanceof java.lang.ClassLoader cl

(6)通過引用查詢物件

select o from instanceof 0xd404d404 o

built-in物件 -- heap

(1)heap.findClass(class name) -- 找到類

select heap.findClass("java.lang.String").superclass

(2)heap.findObject(object id) -- 找到物件

select heap.findObject("0xd404d404")

(3)heap.classes -- 所有類的列舉

select heap.classes

(4)heap.objects -- 所有物件的列舉

select heap.objects("java.lang.String")

(5)heap.finalizables -- 等待垃圾收集的java物件的列舉

(6)heap.livepaths -- 某一物件存活路徑

select heaplivepaths(s) from java.lang.String s

(7)heap.roots -- 堆根集的列舉

辨識物件的函式

(1)classof(class name) -- 返回java物件的類物件

select classof(cl).name from instanceof java.lang.ClassLoader cl

(2)identical(object1,object2) -- 返回是否兩個物件是同一個例項

select identical(heap.findClass("java.lang.String").name, heap.findClass("java.lang.String").name)

(3)objectid(object) -- 返回物件的id

select objectid(s) from java.lang.String s

(4)reachables -- 返回可從物件可到達的物件

select reachables(p) from java.util.Properties p -- 查詢從Properties物件可到達的物件
select reachables(u, "java.net.URL.handler") from java.net.URL u -- 查詢從URL物件可到達的物件,但不包括從URL.handler可到達的物件

(5)referrers(object) -- 返回引用某一物件的物件

select referrers(s) from java.lang.String s where s.count > 100

(6)referees(object) -- 返回某一物件引用的物件

select referees(s) from java.lang.String s where s.count > 100

(7)refers(object1,object2) -- 返回是否第一個物件引用第二個物件

select refers(heap.findObject("0xd4d4d4d4"),heap.findObject("0xe4e4e4e4"))

(8)root(object) -- 返回是否物件是根集的成員

select root(heap.findObject("0xd4d4d4d4")) 

(9)sizeof(object) -- 返回物件的大小

select sizeof(o) from [I o

(10)toHtml(object) -- 返回物件的html格式

select "<b>" + toHtml(o) + "</b>" from java.lang.Object o

(11)選擇多值

select {name:t.name?t.name.toString():"null",thread:t} from instanceof java.lang.Thread t

陣列、迭代器等函式

(1)concat(enumeration1,enumeration2) -- 將陣列或列舉進行連線

select concat(referrers(p),referrers(p)) from java.util.Properties p

(2)contains(array, expression) -- 陣列中元素是否滿足某表示式

select p from java.util.Properties where contains(referres(p), "classof(it).name == 'java.lang.Class'")

返回由java.lang.Class引用的java.util.Properties物件

  • built-in變數
  • it -- 當前的迭代元素
  • index -- 當前迭代元素的索引
  • array -- 被迭代的陣列

(3)count(array, expression) -- 滿足某一條件的元素的數量

select count(heap.classes(), "/java.io./(it.name)")

(4)filter(array, expression) -- 過濾出滿足某一條件的元素

select filter(heap.classes(), "/java.io./(it.name)")

(5)length(array) -- 返回陣列長度

select length(heap.classes())

(6)map(array,expression) -- 根據表示式對陣列中的元素進行轉換對映

select map(heap.classes(),"index + '-->' + toHtml(it)")

(7)max(array,expression) -- 最大值, min(array,expression)

select max(heap.objects("java.lang.String"),"lhs.count>rhs.count")
  • built-in變數
  • lhs -- 左邊元素
  • rhs -- 右邊元素

(8)sort(array,expression) -- 排序

select sort(heap.objects('[C'),'sizeof(lhs)-sizeof(rhs)')

(9)sum(array,expression) -- 求和

select sum(heap.objects('[C'),'sizeof(it)')

(10)toArray(array) -- 返回陣列

(11)unique(array) -- 唯一化陣列

jmap

列印程序、核心檔案或遠端除錯伺服器的共享物件記憶體對映或堆記憶體詳細資訊。

    jmap [option] <pid>
        (to connect to running process) 連線到正在執行的程序

    jmap [option] <executable <core>
        (to connect to a core file)     連線到核心檔案

    jmap [option] [server_id@]<remote server IP or hostname>
        (to connect to remote debug server) 連線到遠端除錯服務

option

  • pid:    目標程序的PID,程序編號,可以採用ps -ef | grep java 檢視java程序的PID;
  • executable:     產生core dump的java可執行程式;
  • core:     將被列印資訊的core dump檔案;
  • remote-hostname-or-IP:     遠端debug服務的主機名或ip;
  • server-id:     唯一id,假如一臺主機上多個遠端debug服務;

使用方法

  1. jmap -dump:[live,]format=b,file=<filename> PID :使用hprof二進位制形式,輸出jvm的heap內容到檔案

  2. jmap -finalizerinfo PID:列印正等候回收的物件的資訊

  3. jmap -heap PID:列印heap的概要資訊,GC使用的演算法,heap(堆)的配置及JVM堆記憶體的使用情況。

  4. jmap -histo:live PID:列印每個class的例項數目,記憶體佔用,類全名資訊。VM的內部類名字開頭會加上字首”*”. 如果live子引數加上後,只統計活的物件數量.

  5. jmap -permstat PID:列印classload和jvm heap長久層的資訊. 包含每個classloader的名字、活潑性、地址、父classloader和載入的class數量。另外,內部String的數量和佔用記憶體數也會打印出來。

  6. -F 強迫.在pid沒有相應的時候使用-dump或者-histo引數。在這個模式下,live子引數無效。

  7. -h | -help 列印輔助資訊

  8. -J 傳遞引數給jmap啟動的jvm.

jstack

jstack命令主要用於除錯java程式執行過程中的執行緒堆疊資訊,可以用於檢測死鎖,程序耗用cpu過高報警問題的排查。jstack命令會打印出所有的執行緒,包括使用者自己啟動的執行緒和jvm後臺執行緒。

命令格式

jstack -[option] pid

option

  • -F 強制dump執行緒堆疊資訊. 用於程序hung住, jstack <pid>命令沒有響應的情況

  • -m 同時列印java和本地(native)執行緒棧資訊,m是mixed mode的簡寫

  • -l 列印鎖的額外信

來源:blog.csdn.net/cong____cong/article/

details/106349866