前言
在jdk中提供了一些工具幫助開發人員解決一些問題。上一篇中提到的jps,jstack就是出自jdk。
jdk/bin目錄下提供了很多exe檔案其實都是jar檔案的包裝,真正的實作在jdk/lib/tools.jar中

jps–檢視Java程序
jps指令可以檢視所有的Java程序
jps存放在JAVA_HOME/bin/jps,使用時為了友善請将JAVA_HOME/bin/加入到Path。
[no1@localhost ~]$ jps
.jar
Jps
- -q 隻顯示pid
- -m 輸出傳遞給main 方法的參數
- -l 輸出應用程式main class的完整package名 或者 應用程式的jar檔案完整路徑名
- -v 輸出傳遞給JVM的參數
jstat–檢視Java虛拟機運作時資訊
可以檢視Java虛拟機運作時資訊,可以檢視堆資訊情況,GC情況
jstat -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]]
參數解釋:
Options — 選項
-class 顯示ClassLoad的相關資訊;
-compiler 顯示JIT編譯的相關資訊;
-gc 顯示和gc相關的堆資訊;
-gccapacity 顯示各個代的容量以及使用情況;
-gccause 顯示垃圾回收的相關資訊(通-gcutil),同時顯示最後一次或目前正在發生的垃圾回收的誘因;
-gcnew 顯示新生代資訊;
-gcnewcapacity 顯示新生代大小和使用情況;
-gcold 顯示老年代和永久代的資訊;
-gcoldcapacity 顯示老年代的大小;
-gcpermcapacity 顯示永久代的大小;
-gcutil 顯示垃圾收集資訊;
-printcompilation 輸出JIT編譯的方法資訊;
-t 可以在列印的列加上Timestamp列,用于顯示系統運作的時間
vmid — VM的程序号,即目前運作的java程序号PID
interval– 間隔時間,機關為秒或者毫秒
count — 列印次數,如果預設則列印無數次
class – 檢視ClassLoad資訊
檢視pid為9415的ClassLoad相關資訊
[no1@localhost ~]$ jstat -class 9415
Loaded Bytes Unloaded Bytes Time
. .08
- Loaded 加載了類的總數量,後面的byte表示加載了類的總大小
- Unloaded 解除安裝了類的總數量,後面的byte表示解除安裝了類的總大小
- Time 加載和解除安裝類所花費的時間
compiler–顯示JIT編譯的相關資訊
[no1@localhost ~]$ jstat -compiler
Compiled Failed Invalid Time FailedType FailedMethod
.
- Compiled 編譯任務執行次數
- Failed 編譯失敗次數
- Invalid 編譯不可用次數
- Time 編譯總耗時
- FailedType 最後一次編譯失敗的類型
- FailedMethod 最後一次編譯失敗的方法和類名
GC – gc相關的堆資訊
- S0C: Survivor0(幸存區0)大小(KB)
- S1C: Survivor1(幸存區1)1大小(KB)
- S0U: Survivor0(幸存區0)已使用大小(KB)
- S1U: Survivor1(幸存區1)已使用大小(KB)
- EC : Eden(伊甸區)大小(KB)
- EU : Eden(伊甸區)已使用大小(KB)
- OC :老年代大小(KB)
- OU : 老年代已使用大小(KB)
- PC : Perm永久代大小(KB)
- PU : Perm永久代已使用大小(KB)
- YGC:新生代GC個數
- YGCT:新生代GC的耗時(秒)
- FGC :Full GC次數
- FGCT:Full GC耗時(秒)
- GCT :GC總耗時(秒)
gccapacity–顯示各個代的容量以及使用情況
- NGCMN:新生代最小值(KB)
- NGVMX:新生代最大值(KB)
- NGC:目前新生代大小(KB)
- S0C:目前新生代s0區大小
- S1C:目前新生代s1區大小
- EC:目前新生代Eden區大小
- OGCMN:老年代最小值(KB)
- OGCMX:老年代最大值(KB)
- OGC:目前老年代大小(KB)
- PGCMN:永久代最小值(KB)
- PGCMX:永久代最大值(KB)
- PGC:目前永久代大小(KB)
gccause – 最近一次GC的原因
- LGCC:上一次GC的原因,是G1垃圾回收器回收
- GCC :目前GC的原因
gcnew – 顯示新生代詳細資訊
- TT:新生代到老年代的年齡;
- MTT:新生代到老年代的最大年齡;
- DSS:所需的survivor的大小;
gcnewcapacity –輸出新生代各個區的詳細資訊
- S0CMX:S0最大空間大小(KB)
- S1CMX:S1最大空間大小(KB)
- ECMX:Eden最大空間大小(KB)
- NGCMX:年輕代最大空間大小(KB)
gcutil–顯示垃圾回收資訊
- S0 — s0區已使用空間的百分比
- S1 — s1區已使用空間的百分比
- E — Eden區已使用空間的百分比
- O — 老年區已使用空間的百分比
- P — 永久區已使用空間的百分比
- YGC — 從應用程式啟動到采樣時發生 Young GC 的次數
- YGCT– 從應用程式啟動到采樣時 Young GC 所用的時間(機關秒)
- FGC — 從應用程式啟動到采樣時發生 Full GC 的次數
- FGCT– 從應用程式啟動到采樣時 Full GC 所用的時間(機關秒)
- GCT — 從應用程式啟動到采樣時用于垃圾回收的總時間(機關秒)
jinfo–檢視虛拟機參數
jinfo可以用來檢視正在運作的Java應用程式的擴充參數,甚至支援運作時修改部分參數。
jinfo <option> pid
pid 即 Java程序ID
options參數可以是如下資訊
- -flag : 列印指定Java虛拟機的參數值
- -flag [+|-] : 設定指定Java虛拟機參數的布爾值
- -flag =:設定某一個參數的值value
例如檢視是否列印GC資訊,這裡是輸出結果 -XX:-PrintGC -表示不列印
[no1@localhost ~]$ jinfo -flag PrintGC
-XX:-PrintGC
修改參數,開啟列印GC
開啟列印GC資訊
再來檢視是否列印GC資訊,發現已經開啟
[no1@localhost ~]$ jinfo -flag PrintGC
-XX:+PrintGC
jmap – java記憶體映像工具
jmap指令可以生成Java程式的堆dump檔案,也可以檢視堆對象執行個體的統計資訊,檢視ClassLoader的資訊以及finalizer隊列。
使用方式:jmap [ option ] pid
- -dump:[live,]format=b,file= 使用hprof二進制形式,輸出jvm的heap内容到檔案=. live子選項是可選的,假如指定live選項,那麼隻輸出活的對象到檔案.
- -finalizerinfo 列印正等候回收的對象的資訊.
- -heap 列印heap的概要資訊,GC使用的算法,heap的配置及wise heap的使用情況.
- -histo[:live] 列印每個class的執行個體數目,記憶體占用,類全名資訊. VM的内部類名字開頭會加上字首”*”. 如果live子參數加上後,隻統計活的對象數量.
- -permstat 列印classload和jvm heap長久層的資訊. 包含每個classloader的名字,活潑性,位址,父classloader和加載的class數量.另外,内部String的數量和占用記憶體數也會列印出來.
histo列印class類的執行個體
jmap -histo > c:/txt
輸出:
dump堆資訊
[[email protected] ~]$ jmap -dump:format=b,file=/home/no1/dump.hprof
Dumping heap to /home/no1/dump.hprof ...
Heap dump file created
dump出的檔案可以用 jhat(不推薦使用,功能有限),visual vm,MAT,IBM heapAnalyzer,Eclipse Memory Analyzer等打開檢視
jhat–jdk自帶的堆分析工具
不推薦使用,功能有限,并且一般情況下導出伺服器上的機器堆資訊都不會在伺服器上進行分析消耗資源,而是拿到其他機器進行分析。
visual vm,MAT,IBM heapAnalyzer,Eclipse Memory Analyzer等這些都可以代替它。
jstack–堆棧跟蹤工具
jstack(stack Trace for Java) 指令用于生成虛拟機目前時刻的線程快照。線程快照即:目前虛拟機内每一個線程正在執行的方法的堆棧集合。可以通過這個快照看到每一個線程都執行在哪個方法上了,狀态是什麼樣子的(運作,等待等)。
jstack -l pid
[[email protected] ~]$ jstack -l
-- ::
Full thread dump Java HotSpot(TM) -Bit Server VM (-b12 mixed mode):
"Attach Listener" #12 daemon prio=9 os_prio=0 tid=0x00007f2414001000 nid=0x277b waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"DestroyJavaVM" #11 prio=5 os_prio=0 tid=0x00007f2450008800 nid=0x2749 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"Thread-2" #10 prio=5 os_prio=0 tid=0x00007f2450175000 nid=0x2756 waiting on condition [0x00007f243d8dd000]
java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(Native Method)
at HoldIOMain$T2.run(HoldIOMain.java:)
at java.lang.Thread.run(Thread.java:)
Locked ownable synchronizers:
- None
"Thread-1" #9 prio=5 os_prio=0 tid=0x00007f2450173800 nid=0x2755 waiting on condition [0x00007f243d9de000]
java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(Native Method)
at HoldIOMain$T2.run(HoldIOMain.java:)
at java.lang.Thread.run(Thread.java:)
Locked ownable synchronizers:
- None
"Thread-0" #8 prio=5 os_prio=0 tid=0x00007f2450171800 nid=0x2754 runnable [0x00007f243dadf000]
java.lang.Thread.State: RUNNABLE
at java.io.FileOutputStream.write(Native Method)
at java.io.FileOutputStream.write(FileOutputStream.java:)
at HoldIOMain$T1.run(HoldIOMain.java:)
at java.lang.Thread.run(Thread.java:)
Locked ownable synchronizers:
- None
jcmd
在JDK 1.7之後,新增了一個指令行工具jcmd。它是一個多功能工具,可以用來導出堆,檢視java程序,導出線程資訊,執行GC等。
jcmd具有jmap指令大部分功能,oracle官方網站推薦jcmd替代jmap。
檢視正在運作的虛拟機
[[email protected] ~]$ jcmd -l
/home/no1/soft/jar
sun.tools.jcmd.JCmd -l
參數說明:jcmd -l 可以檢視所有的Java虛拟機,類似jps
檢視指定虛拟機
-l指令是列出所有Java虛拟機,針對每一個虛拟機可以通過help指令查詢所支援的指令。
文法 jcmd pid help
[[email protected] ~]$ jcmd help
:
The following commands are available:
JFR.stop
JFR.start
JFR.dump
JFR.check
VM.native_memory
VM.check_commercial_features
VM.unlock_commercial_features
ManagementAgent.stop
ManagementAgent.start_local
ManagementAgent.start
GC.rotate_log
Thread.print
GC.class_stats
GC.class_histogram
GC.heap_dump
GC.run_finalization
GC.run
VM.uptime
VM.flags
VM.system_properties
VM.command_line
VM.version
help
VM.uptime–檢視虛拟機啟動時間
[no1@localhost ~]$ jcmd VM.uptime
:
s
Thread.print – 列印線程棧資訊
GC.heap_dump–導出堆資訊
[no1@localhost ~]$ jcmd GC.heap_dump /home/no1/gcdump.dump
:
Heap dump file created
VM.system_properties – 擷取系統properties
Jconsole–Java監視與管理控制台
Jconsole是jdk自帶的圖形化工具,在%JAVA_HOME%/bin 目錄下jconsole.exe打開即可啟動。
可以連接配接本地和遠端連接配接兩種方式。
編輯tomcat下 catalina.bat 檔案 在 set JAVA_OPTS 加上參數即可
配置資訊如下:設定ip,端口,不需要認證(不需要賬号密碼),不開啟ssl
-Djava.rmi.server.hostname=
-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
需要賬号密碼:設定ip,端口,需要賬号密碼認證,不開啟ssl,
找到jdk目錄結果下的jmxremote.password.template檔案,将其重命名為jmxremote.password,這個檔案裡面設定使用者的密碼,并且要把這個檔案權限改成目前使用者讀寫,在linux中就是600
裡面還有一個jmxremote.access檔案是用來控制使用者操作權限的,jmxremote.password控制使用者的密碼
-Djava.rmi.server.hostname=
-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=
-Dcom.sun.management.jmxremote.authenticate=true
-Dcom.sun.management.jmxremote.pwd.file=D:/jdk1_40/jre/lib/management/jmxremote.password
-Dcom.sun.management.jmxremote.ssl=false
概覽資訊
堆資訊檢視,新生代,永久帶,老年代。等
線程資訊檢視,檢視線程狀态,目前運作方法等
運作參數vm概要
VisualVM–多合一故障處理工具
VisualVM是一個多功能合一的故障診斷,性能監控的可視化工具。內建了多種性能統計工具的功能,在jdk update7版本以後跟随jdk一起釋出,也可以去官網獨立下載下傳http://visualvm.java.net/。
VisualVm可以做到:
- 顯示虛拟機程序的配置和環境資訊(jps,jinfo)
- 監視應用程式的GC,CPU,堆,方法區,線程資訊(jstack,jstat)
- dump及分析堆轉儲快照(jmap,jhat)
- 方法級的程式性能分析,找出被調用最多,運作時間最長的方法。
- 很多其他插件(plugins)
啟動
在%JAVA_HOME%/bin目錄下jvisualvm.exe 輕按兩下即可打開。
左側本地會列出機器上的所有Java程式:圖中有tomcat,eclipse,visual vm。
遠端 可以連接配接到遠端機器的Java虛拟機進行檢測。需要通過jstatd。
快照可以浏覽導出的本地檔案進行分析。
插件
工具–》插件
這裡 如果檢查更新之後無法使用。可能就是配置的更新位址有問題,需要更改一下,如下圖進行編輯。
這個位址對照 插件的位址 https://visualvm.github.io/pluginscenters.html
Btrace插件–動态日志跟蹤
Btrace可以在不停機的情況下,通過位元組碼的注入動态監控系統運作的情況,可以跟蹤指定的方法調用,構造函數調用和系統記憶體等資訊。
如圖選擇 Btrace workbench進行安裝。
安裝完成之後選擇左邊的Java程式右鍵點選trace application就可以打開Btrace了
如圖這裡選擇tomcat右鍵操作
Java代碼
Java代碼:接收控制台輸入的兩個數字,輸出兩個數字求和的結果
package com.jx;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class BtraceTest{
public int add(int a,int b){
return a+b;
}
public static void main(String[] args) {
try {
BtraceTest test = new BtraceTest();
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
int a = ,b = ;
for(int i = ; i < ; i++){
String line = reader.readLine();
if(i == ){
a = Integer.parseInt(line);
}else{
b = Integer.parseInt(line);
}
}
reader.close();
System.out.println(test.add(a, b));
} catch (IOException e) {
e.printStackTrace();
}
}
}
Btrace代碼
import com.sun.btrace.BTraceUtils;
import static com.sun.btrace.BTraceUtils.*;
import com.sun.btrace.annotations.*;
@BTrace
public class Btrace {
@OnMethod(
clazz="com.jx.BtraceTest",
method="add",
location=@Location(Kind.RETURN)
)
public static void functest(@Self com.jx.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)));
}
}
運作
先運作Java代碼,等待輸入數字。
這個時候可以visualvm監控到Java程式已經運作,右鍵選擇Java程式 trace application 輸入 trace 代碼,點選start就可以開始監控。
回到Java程式輸入數字 回過頭來可以看到 trace 監聽到了參數和傳回值。
* Starting BTrace task
** Compiling the BTrace script ...
*** Compiled
** Instrumenting classes ...
*** Done
** BTrace up&running
*** Done
** BTrace up&running
調用堆棧
com.jx.BtraceTest.add(BtraceTest.java:)
com.jx.BtraceTest.main(BtraceTest.java:)
方法參數A5
方法參數B3
傳回結果
** BTrace has stopped
** BTrace has stopped