相關資料
- jstat java性能統計工具
- jstack java線程堆棧工具
- jmap java記憶體映像工具
- jps java程序檢視
- jinfo java配置資訊工具
- jhat java堆快照分析工具
- jconsole 可視化java工具
- jvisualvm 可視化java工具
- jstatd java統計監控背景程式
- jdb java調試工具
jps 簡介
列出所有java程序
options
-q 僅輸出VM辨別符,不包括class name,jar name,arguments in main method
-m 輸出main method的參數
-l 輸出完全的包名,應用主類名,jar的完全路徑名
-v 輸出jvm參數
-V 輸出通過flag檔案傳遞到JVM中的參數(.hotspotrc檔案或-XX:Flags=所指定的檔案
-Joption 傳遞參數到vm,例如:-J-Xms48m
hostid
[protocol:][[//]hostname][:port][/servername]
Examples
jps rmi:.*.*.*: # 檢視遠端機器的java程序id(需要遠端開啟jstatd程序)
jps -lmv # 本地java程序的詳細資訊
jinfo 簡介
jinfo可以輸出并修改運作時的java 程序的opts。用處比較簡單,用于輸出JAVA系統參數及指令行參數。一般不支援修改,jdk8廢棄改指令。
jinfo [ option ] pid
jinfo [ option ] executable core
jinfo [ option ] [server[email protected]]remote-hostname-or-IP
Options
no option 列印指令行參數和系統屬性
-flags 列印指令行參數
-sysprops 列印系統屬性
-h 幫助
jstatd 簡介
虛拟機的監控的守護程序,主要用于監控JVM的建立與終止,并提供一個接口允許遠端監控工具(jps|jstat|jstack…)依附到在本地主機上運作的JVM。
Options
-nr 當一個存在的RMI Registry沒有找到時,不嘗試建立一個内部的RMI Registry
-p port 端口号,預設為
-n rminame 預設為JStatRemoteHost;如果多個jstatd服務開始在同一台主機上,rminame唯一确定一個jstatd服務
-J jvm選項
Usages
- 通過政策檔案(jstatd.all.policy),允許jstatd伺服器在沒有任何安全例外的情況下運作。該政策沒有授權所有權限給所有代碼庫那麼自由,但卻比授予最小的權限來運作jstatd伺服器更自由.個人建議要及時關閉,有風險。
grant codebase "file:${java.home}/../lib/tools.jar" {
permission java.security.AllPermission;
};
- 基于政策檔案,啟動jstatd,同時啟動RMI日志(一般沒必要就不要開啟了)
nohup rmiregistry &jstatd -J-Djava.security.policy=jstatd.all.policy -J-Djava.rmi.server.logCalls=true -p &
jstat 簡介
jvm監控統計工具,包括gc資訊,類編譯資訊等。
jstat [ generalOption | outputOptions vmid [interval[s|ms] [count]] ]
vmid
[protocol:][//]lvmid[@hostname[:port]/servername]
options
-class | 類加載情況的統計 |
Loaded | 加載了的類的數量 |
Bytes | 加載了的類的大小,單為Kb |
Unloaded | 解除安裝了的類的數量 |
Bytes | 解除安裝了的類的大小,單為Kb |
Time | 花在類的加載及解除安裝的時間 |
-compiler | HotSpot中即時編譯器編譯情況的統計 |
Compiled | 編譯任務執行的次數 |
Failed | 編譯任務執行失敗的次數 |
Invalid | 編譯任務非法執行的次數 |
Time | 執行編譯花費的時間 |
FailedType | 最後一次編譯失敗的編譯類型 |
FailedMethod | 最後一次編譯失敗的類名及方法名 |
-gc | JVM中堆的垃圾收集情況的統計 |
S0C | 新生代中Survivor space中S0目前容量的大小(KB) |
S1C | 新生代中Survivor space中S1目前容量的大小(KB) |
S0U | 新生代中Survivor space中S0容量使用的大小(KB) |
S1U | 新生代中Survivor space中S1容量使用的大小(KB) |
EC | Eden space目前容量的大小(KB) |
EU | Eden space容量使用的大小(KB) |
OC | Old space目前容量的大小(KB) |
OU | Old space使用容量的大小(KB) |
PC | Permanent space目前容量的大小(KB) |
PU | Permanent space使用容量的大小(KB) |
YGC | 從應用程式啟動到采樣時發生 Young GC 的次數 |
YGCT | 從應用程式啟動到采樣時 Young GC 所用的時間(秒) |
FGC | 從應用程式啟動到采樣時發生 Full GC 的次數 |
FGCT | 從應用程式啟動到采樣時 Full GC 所用的時間(秒) |
GCT | T從應用程式啟動到采樣時用于垃圾回收的總時間(機關秒),它的值等于YGC+FGC |
-gccapacity | 新生代、老生代及持久代的存儲容量情況 |
NGCMN | 新生代的最小容量大小(KB) |
NGCMX | 新生代的最大容量大小(KB) |
NGC | 目前新生代的容量大小(KB) |
S0C | 目前新生代中survivor space 0的容量大小(KB) |
S1C | 目前新生代中survivor space 1的容量大小(KB) |
EC | Eden space目前容量的大小(KB) |
OGCMN | 老生代的最小容量大小(KB) |
OGCMX | 老生代的最大容量大小(KB) |
OGC | 目前老生代的容量大小(KB) |
OC | 目前老生代的空間容量大小(KB) |
PGCMN | 持久代的最小容量大小(KB) |
PGCMX | 持久代的最大容量大小(KB) |
PGC | 目前持久代的容量大小(KB) |
PC | 目前持久代的空間容量大小(KB) |
YGC | 從應用程式啟動到采樣時發生 Young GC 的次數 |
FGC | 從應用程式啟動到采樣時發生 Full GC 的次數 |
-gccause | 這個選項用于檢視垃圾收集的統計情況(這個和-gcutil選項一樣),如果有發生垃圾收集,它還會顯示最後一次及目前正在發生垃圾收集的原因,它比-gcutil會多出最後一次垃圾收集原因以及目前正在發生的垃圾收集的原因。用于檢視垃圾收集的統計情況,包括最近發生垃圾的原因 |
LGCC | 最後一次垃圾收集的原因,可能為“unknown GCCause”、“System.gc()”等 |
GCC | 目前垃圾收集的原因 |
-gcutil | 新生代、老生代及持代垃圾收集的情況 |
S0 | Heap上的 Survivor space 0 區已使用空間的百分比 |
S1 | Heap上的 Survivor space 1 區已使用空間的百分比 |
E | Heap上的 Eden space 區已使用空間的百分比 |
O | Heap上的 Old space 區已使用空間的百分比 |
P | Perm space 區已使用空間的百分比 |
YGC | 從應用程式啟動到采樣時發生 Young GC 的次數 |
YGCT | 從應用程式啟動到采樣時 Young GC 所用的時間(機關秒) |
FGC | 從應用程式啟動到采樣時發生 Full GC 的次數 |
FGCT | 從應用程式啟動到采樣時 Full GC 所用的時間(機關秒) |
GCT | 從應用程式啟動到采樣時用于垃圾回收的總時間(機關秒),它的值等于YGC+FGC |
-printcompilation | HotSpot編譯方法的統計 |
Compiled | 編譯任務執行的次數 |
Size | 方法的位元組碼所占的位元組數 |
Type | 編譯類型 |
Method | 指定确定被編譯方法的類名及方法名,類名中用“/”而不是“.”做為命名分隔符,方法名是被指定的類中的方法,這兩個字段的格式是由HotSpot中的“-XX:+PrintComplation”選項确定的。 |
-JjavaOption | 用于将給定的javaOption傳給java應用程式加載器,例如,“-J-Xms48m”将把啟動記憶體設定為48M。如果想檢視可以傳遞哪些選項到應用程式加載器中,可以相看如下的文檔 |
Linux and Solaris: | http://docs.oracle.com/javase/1.5.0/docs/tooldocs/solaris/java.html |
Windows: | http://docs.oracle.com/javase/1.5.0/docs/tooldocs/windows/java.html |
-t n | 用于在輸出内容的第一列顯示時間戳,這個時間戳代表的時JVM開始啟動到現在的時間 |
-h n | 用于指定每隔幾行就輸出列頭,如果不指定,預設是隻在第一行出現列頭 |
Examples
jstat -gc rmi:pid@10.*.*.*: # 檢視遠端機器 指定pid的gc 資訊
jstat -class pid # 本地java程序[pid]的類加載情況的統計
Reference
- jvm記憶體結構及管理
- jvm gc 詳情
jstack 簡介
jstack用于列印出給定的Java程序ID或core file或遠端調試服務的Java堆棧資訊,如果是在64位機器上,需要指定選項”-J-d64”,Windows的jstack使用方式隻支援以下的這種方式:jstack [-l] pid
如果java程式崩潰生成core檔案,jstack工具可以用來獲得core檔案的java stack和native stack的資訊,進而可以輕松地知道java程式是如何崩潰和在程式何處發生問題。另外,jstack工具還可以附屬到正在運作的java程式中,看到當時運作的java程式的java stack和native stack的資訊, 如果現在運作的java程式呈現hung的狀态,jstack是非常有用的。
jstack [ option ] pid #(Usually)
jstack [ option ] executable core
jstack [ option ] [[email protected]]remote-hostname-or-IP
Option
-F #當’jstack [-l] pid’沒有相應的時候強制列印棧資訊
-l #長清單. 列印關于鎖的附加資訊,例如屬于java.util.concurrent的ownable synchronizers清單.
-m #列印java和native c/c++架構的所有棧資訊.
-h|-help #列印幫助資訊
jstack内容詳解
- java線程狀态
- java線程狀态轉移
java常用工具相關資料jps 簡介jinfo 簡介jstatd 簡介jstat 簡介jstack 簡介jmap 簡介jhat 簡介jdb簡介jconsole簡介jvisualvm 簡介常見問題
線程被阻塞可能是由于下面五方面的原因:
1.調用sleep(毫秒數),使線程進入睡眠狀态。在規定時間内,這個線程是不會運作的。
2.用suspend()暫停了線程的執行。除非收到resume()消息,否則不會傳回“可運作”狀态。(已廢棄)
3.用wait()暫停了線程的執行。除非線程收到notify()或notifyAll()消息,否則不會變成“可運作”狀态。
4.線程正在等候一些IO操作完成。
5.線程試圖調用另一個對象的“同步”方法,但那個對象處于鎖定狀态,暫時無法使用。
所涉及到的兩種池:
Wait pool 等待池
Lock pool 鎖池
- jstack 幾種線程狀态介紹
Runnable #包括runnable和running兩種狀态
Wait on condition #線程等待IO,sleep等
Waiting for monitor entry #對象在Lockpool中
in Object.wait() #對象在wait pool 中需要notify才能進入鎖池,并最終獲得鎖進入Runnable狀态
- jstack分析執行個體
jstack分析幾種常見問題
io異常
- 當jstack dump 的線程中存在大量的 wait on condition ,觀察堆棧是不是網絡IO 導緻的,結合系統指令 netstat 觀察是不是已經超過帶寬的上限。
- lsof -p $pid 觀察目前程序的io請況
- iostat 觀察系統總體的io情況
死鎖
jstack 會自動識别并表示死鎖。
熱鎖
熱鎖,也往往是導緻系統性能瓶頸的主要因素。其表現特征為,由于多個線程對臨界區,或者鎖的競争,可能出現:
- 頻繁的線程的上下文切換:從作業系統對線程的排程來看,當 線程在等待資源而阻塞的時候,作業系統會将之切換出來,放到等待的隊列,當線程獲得資源之後,排程算法會将這個線程切換進去,放到執行隊列中。
- 大量的系統調用:因為線程的上下文切換,以及熱鎖的競争,或 者臨界區的頻繁的進出,都可能導緻大量的系統調用。
- 大部分 CPU開銷用在 “系統态 ”:線程上下文切換,和系統調用,都會導緻 CPU在 “系統态 ”運作,換而言之,雖然系統很忙碌,但是 CPU用在 “使用者态 ”的比例較小,應用程式得不到充分的 CPU資源。
- 随着 CPU數目的增多,系統的性能反而下降。因為 CPU數目多,同 時運作的線程就越多,可能就會造成更頻繁的線程上下文切換和系統态的 CPU開銷,進而導緻更糟糕的性能。
結合系統指令top -p $pid; shift +h ;以及具體堆棧分析定位系統态的cpu占用過高的具體原因。
cpu過高
- 結合系統指令定位具體的程序中某個導緻程序cpu過高的線程pid。
- printf(“%x\n”) $pid 轉換十六進制;對應堆棧中的nid(nid 是實際的本地系統的程序id,tid 是虛拟機中的程序id)。
- 通過堆棧資訊,分析該線程pid的具體資訊。
程式效率低,執行慢
分析是否存在死鎖,熱鎖。分析WAITING,BLOCK,狀态的線程。觀察是不是IO導緻的,網絡IO,帶寬問題,還是網絡斷開導緻的空等待,還是線程sleep,waitpool中的對象是不是忘記喚醒,lockpool的對象是不是永遠擷取不到鎖,TIMED_WAIT設定的時間是否合理,或者磁盤IO導緻的,具體問題結合堆棧資訊和系統狀态進行分析。(vmstat,iostat,netstat,uptime,top。lsof等指令根據需要配合使用。)
jmap 簡介
列印出某個java程序記憶體的,所有‘對象’的情況。64位機器上,需要指定選項”-J-d64”。
jmap [ option ] pid #(Usually)
jmap [ option ] executable core
jmap [ option ] [[email protected]]remote-hostname-or-IP
Options
-dump:[live,]format=b,file=<filename> #使用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的數量和占用記憶體數也會列印出來.
-F #強迫在pid沒有相應的時候使用-dump或者-histo參數. 在這個模式下,live子參數無效.
-h | -help #列印輔助資訊
-J #傳遞參數給jmap啟動的jvm.
Example
jmap -dump:format=b,file=tomcat.bin
jmap -histo:live $cpid
jhat 簡介
用來分析Java堆的指令,可以将堆中的對象以html的形式顯示出來,包括對象的數量,大小等等,并支援對象查詢語言.
- jhat tomcat.bin (jmap dump的檔案)
- dump出來的堆很大,在啟動時會報堆空間不足的錯。添加 -J-Xmx512m,重定義最大堆記憶體
- ip:7000 浏覽器檢視
- http://ip:7000/histo/ 類大小,數量統計資訊
- http://ip:7000/showRoots/ gc根集
- http://ip:7000/oql/ 對象查詢
- http://ip:7000/oqlhelp/ 對象查詢文法
jdb簡介
java debug 工具,一般使用IDE,debug更快捷,無界面程式可以使用該工具調試。
指令行調試
jdb調試指令
JAVA_OPTS="$JAVA_OPTS -Xdebug -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y"
jdb -attach .:
jconsole簡介
JConsole 是一個内置 Java 性能分析器,可以從指令行或在 GUI shell 中運作。
Usages jconsole
jvisualvm 簡介
jconsole的更新版。
Usages jvisualvm
常見問題
sun.jvm.hotspot.debugger.DebuggerException 異常
出現場景
- jinfo pid
- jstack -F
- jmap -heap
Solve
sudo vim /etc/sysctl.d/-ptrace.conf
修改 kernel.yama.ptrace_scope =
sudo /sbin/sysctl -e -p /etc/sysctl.d/-ptrace.conf 重新加載該調整資訊,無需重新開機,永久有效
echo | sudo tee /proc/sys/kernel/yama/ptrace_scope 目前有效,重新開機後無效,建議使用後恢複本來的設定,ubuntu從後修改了該預設設定,應該是出于安全考慮,線上環境,更應該謹慎使用。
sun.jvm.hotspot.runtime.VMVersionMismatchException
工具和pid的jvm不一緻導緻的,使用啟動目前pid的java指令所在的檔案夾下的工具指令。