最近有些空閑的時間,看了一些JVM內存管理方面的知識,由于JDK自帶了一些工具用于Java的故障排除,性能分析,監控和管理等。從本章開始以及后續的文章將進行這方面的實踐活動。
一、JDK監控類工具
注:文章中提及的工具均在java安裝目錄的/bin目錄下
[1] jps -- Java Virtual Machine Process Status Tool
jvm進程狀態工具,可以列出本機所有java進程的pid。該命令類似于linux的ps命令哦。
1.概要
jps [ options ] [ hostid ]
options
-q 禁止輸出類的名稱,JAR文件的名稱,傳遞給方法的參數,主要產生本地VM標識符列表(即只輸出pid列表);
-m 輸出傳遞給main方法的參數,嵌入式JVM可能輸出為空;
-l 輸出應用程序主類的全包名或者應用程序jar文件的全路徑名;
-v 輸出傳遞給JVM的參數;
-V 輸出通過flag文件傳遞到JVM中的參數(.hotspotrc文件或由-XX:Flags=<filename>指定的參數);
-Joption 傳遞參數到vm,例如:-J-Xms48m
hostid
[protocol:][[//]hostname][:port][/servername]
2.輸出格式
lvmid [ [ classname | JARfilename | "Unknown"] [ arg* ] [ jvmarg* ] ]
3.示例
(1) jps 僅顯示進程id,主類名

(2) jps -q 僅顯示進程id

(3)jps -l 輸出完全的包名,主類名,jar完全路徑名

(4)jps -v 顯示jvm參數(如果對jvm參數不熟悉,請看《深入JVM內幕》)

jps –l 127.0.0.1 輸出127.0.0.1機器上的java進程,顯示完全的包名,主類名,jar完全路徑
注意:127.0.0.1主機要啟動jstatd (關于如何啟動jstatd,請參見jstated)

參考:
http://download.oracle.com/javase/6/docs/technotes/tools/share/jps.html
[2] Jstated --Virtual Machine jstat Daemon(虛擬機jstat守護進程)
jstatd工具是一個RMI服務器應用程序,用來監視Java虛擬機(JVM)的創建和終結,它提供了一個接口,允許遠程監控工具連接到運行在本地主機上的JVM。
jstatd 服務需要本地存在一個RMI注冊. jstatd服務將嘗試依附于RMI注冊,使用默認端口上,或者用-p指定的端口上. 假如rmi注冊沒有找到,jstatd應用將會創建一個使用指定端口或默認端口. 如果jstatd的參數指定了-nr選項,那么創建一個內部的RMI注冊是被禁止的。
1.概要
jstatd [ options ]
options
-nr 當一個存在的RMI注冊表未被找到時,jstatd將不試圖創建一個內部的RMI注冊表;
-p port 期望的RMI注冊端口號,或者自己創建的RMI注冊的端口號;
-n rminame 綁定在RMI注冊表中的遠程RMI對象的名稱,默認為JstatRemoteHost;假如啟動多個jstatd進程,那么就需要用這個參數指定名字以區分.
-Joption 傳遞參數到vm,例如:-J-Xms48m
2.securty
jstatd服務只能在合適的內部訪問權限下啟動. 因此jstatd進程必須用啟動JVMs的同用戶啟動. 一些用戶的權限,如root用戶擁有該機所有JVMs的訪問權限,可以啟動jstatd,但是會引入額外的安全問題.jstatd服務沒有為客戶端提供任何驗證. 所以他會把jstatd進程訪問的jvms暴露給網絡中所有的用戶. 啟動jstatd進程的時候需要考慮一下,你的網絡是否安全,特別是在產品環境中.
在jstatd服務啟動的時候引入一個policy文件將不會有任何安全的異常.

grant codebase "file:${java.home}/../lib/tools.jar"
{

permission java.security.AllPermission;

};

將以上內容保存到名為jstatd.all.policy的當前目錄文件中
然后啟動jstatd
jstatd -J-Djava.security.policy=jstatd.all.policy
3.示例
(1)使用內部RMI注冊表
jstatd -J-Djava.security.policy=jstatd.all.policy (默認端口為1099)
jps –l 127.0.0.1

(2)使用外部RMI注冊表
rmiregistry 2020&
jstatd -J-Djava.security.policy=all.policy -p 2020
jps –l localhost:2020 (等價于遠程監控訪問)
參考:http://download.oracle.com/javase/6/docs/technotes/tools/share/jstatd.html[3] jstat - Java Virtual Machine Statistics Monitoring Tool
主要利用JVM內建的指令對Java應用程序的資源和性能進行實時的命令行的監控,包括了對Heap size和垃圾回收狀況的監控。
概述
jstat [ generalOption | outputOptions vmid [interval[s|ms] [count]] ]
參數
generalOption(常規選項)
一個常規命令行選項(-help, -options, or -version)。如果你指定了常規選項中的一個,您就不能指定任何其他的選項或者參數。
outputOptions
一個或多個輸出選項,由單一的statOption構成,加上-t、-h和-Joptions。
vmid
虛擬機標識符,一個指向目標jvm的字符串,一般語法如下:
[protocol:][//]lvmid[@hostname[:port]/servername]
Interval
采樣間隔單位,秒(S)或毫秒(ms)。默認單位是毫秒,必須為正整數。
count
樣品數量。默認值是無限的,必須為正整數。
generalOption詳細說明
-help
顯示幫助信息
-version
顯示版本信息
-options
顯示統計選項列表。參看后面的output options一節。
如果你未指定常規選型,那么你就可以指定輸出選項了。輸出選項確定jstat的輸出內容和格式,并且由單一的statOption構成,再加上其它輸出選項(- h,- t和- J)。statOption必須放在第一位。
輸出的格式為表,列用空格隔開。帶有標題的標題行用來描述列。使用-h來設置標題顯示的頻次。列標題名在不同的選項之間通常是一致的。通常情況下,如果兩個選項提供具有相同名稱的列,那么這兩個列的數據源是相同的。
使用-t選項顯示一個時間戳列,標注的時間戳將作為輸出的第一列。當目標jvm啟動后,時間戳列記錄了消耗的時間,以秒來進行刻畫。
使用間隔和計數參數,以確定jstat輸出的頻次和次數。
outputOptions詳細說明
-statOption
class 類加載器行為信息的統計
compiler 編譯器行為信息的統計;
gc 堆的垃圾收集行為信息的統計;
gccapacity 各代(新生代、舊生代、持久代)的容量以及它們相應空間信息的統計;
gccause 垃圾收集統計匯總(與 –gcutil相同),包括過去和當前垃圾收集事件的成因;
gcnew 對新生代行為信息的統計;
gcnewcapacity 對新生代的大小以及它們相應的空間的統計;
gcold 對舊生代以及持久代行為信息的統計;
gcoldcapacity 舊生代大小信息的統計;
gcpermcapacity 持久代大小信息的統計;
gctuil 垃圾收集統計匯總;
printcompilation 編譯方法統計;
-h n
表示每n個樣本(輸出行)顯示一個列標題,其中n是正整數,默認值是0。列標題要顯示在上述樣本數據的第一行中。
-t n
表示時間戳列作為輸出的第一列。時間戳時間是自目標jvm開始的時間。
-JjavaOption
傳遞javaOption給java程序啟動器。例如,-JXms48m 設置為48m的內存啟動。
statOptions and Output
下列表格匯總了針對每個statOption的jstat輸出的列;
-class 選項
列 |
描述 |
Loaded |
加載類的數量 |
Bytes |
加載的字節數 |
Unloaded |
卸載類的數量 |
Bytes |
卸載字節數 |
Time |
執行加載和卸載操作花費的時間 |
-compiler 選項
列 |
描述 |
Compiled |
執行的編譯任務數量 |
Failed |
編譯任務失敗的數量 |
Invalid |
無效的編譯任務的數量 |
Time |
執行編譯任務所消耗的時間 |
FailedType |
最后編譯失敗的編譯類型 |
FailedMethod |
最后編譯失敗的類名與方法 |
-gc 選項
列 |
描述 |
S0C |
新生代survibor space 0 區(S0)的容量(KB) |
S1C |
新生代survibor space 1 區(S1)的容量(KB) |
S0U |
S0使用(KB) |
S1U |
S1使用(KB) |
EC |
新生代Eden space容量(KB) |
EU |
Eden space使用(KB) |
OC |
舊生代的容量(KB) |
OU |
舊生代使用(KB) |
PC |
持久代容量(KB) |
PU |
持久代使用(KB) |
YGC |
從應用程序啟動到采樣時發生 Young GC 的次數 |
YGCT |
Young GC 所用的時間(單位秒) |
FGC |
Full GC 次數 |
FGCT |
Full GC 所用的時間(單位秒) |
GCT |
垃圾回收的總時間(單位秒) |
-gcutil 選項
列 |
描述 |
S0 |
Heap上Survivor space 0 區已使用空間的百分比 |
S1 |
Survivor space 1 區已使用空間的百分比 |
E |
Eden space 區已使用空間的百分比 |
O |
Old space 區已使用空間的百分比 |
P |
Perm space 區已使用空間的百分比 |
YGC |
從應用程序啟動到采樣時發生 Young GC 的次數 |
YGCT |
Young GC 所用的時間(單位秒) |
FGC |
Full GC 次數 |
FGCT |
Full GC 所用的時間(單位秒) |
GCT |
垃圾回收的總時間(單位秒) |
|
|
其他選項的輸出,請查看reference
例子
(1)使用gc選項
在使用gc選項之前,首先要通過jps獲得jvm的vmid,如下:
從圖中可以看到,有3個java進程,2500是一個tomcat進程,tomcat對應一個jvm實例。
通過jstat –gc 2500我們能夠看到如下信息,S0、S1、Eden space的容量以及使用量,舊生代、持久代的容量以及使用量,Younc GC和Full GC的次數以及GC的時間,GC總時間。

(2)使用gcutil
對vmid為2500的jvm進行采樣,采樣的數量為10,時間間隔為10秒。
從上圖中我們看到,舊生代、持久代的使用率很高,尤其是持久代最高已經達到99.78%,因此,在內容容量許可的情況下,需要對heap的持久代以及舊生代的內存進行調整。
紅色的框表示,在兩次采樣期間,JVM發生了3此Young GC,Survivor Space從56.41%降低到37.53%,Eden space由94.73%降低到10.63%。并且在GC期間,至少發生了一次從S1區到S0區的對象復制。
常駐內存區(P-持久代)的使用率,始終停留在99%左右,說明常駐內存沒有突變,比較正常。如果young gc和full gc能夠正常發生,而且都能有效回收內存,常駐內存區變化不明顯,則說明java內存釋放情況正常,垃圾回收及時,java內存泄露的幾率就會大大降低。但也不能說明一定沒有內存泄露。
posted on 2011-06-20 11:38
zhangxl 閱讀(674)
評論(0) 編輯 收藏 所屬分類:
java tools