java開發-JVM監控調優

調優文章鏈接:
http://blog.csdn.net/wisgood/article/details/25343845

調優工具VisualVM使用教程:
https://www.ibm.com/developerworks/cn/java/j-lo-visualvm/

1. 前期準備條件

本地環境需要安裝JDK,然後配置環境變量。
在DOC窗口通過各種java命令就可以查看JVM運行狀態了。

2. 通過jps命令查看JVM裏進程狀態

2.1 輸出JVM裏所有進程的完整路徑名:jps -l

結果:
這裏寫圖片描述
如果需要查看其他機器上的jvm進程,需要在待查看機器上啓動jstatd遠程服務。因爲遠程查看JVM狀態,是基於RMI協議的,因此需要遠程主機開啓jstatd遠程服務。

2.2 遠程機器開啓jstatd服務

(1)創建jstatd服務器授權文件jstatd.all.policy,代碼如下,然後將改文件放到Java/bin目錄下。

grant codebase "file:${java.home}/../lib/tools.jar" {
permission java.security.AllPermission;
};

(2) 切換到java/bin目錄下,執行以下命令啓動jstatd服務器
jstatd -J-Djava.security.policy=jstatd.all.policy

(3)如若出現默認端口1099被佔用,在啓動jstatd服務器時,可以選擇其它端口。
//查看端口是否被佔用
netstat -ano | grep -i 1099

//啓動jstatd服務器時,指定其它端口
rmiregistry 2030 & jstatd -J-Djava.security.policy=jstatd.all.policy -p 2030

注意:啓動jstatd服務的DOC窗口不要關閉,否則服務就停了。可以新開啓一個窗口用來執行別的命令,這個窗口就開着吧。至此,jstatd服務啓動完畢。

2.3 輸出JVM裏所有進程的JVM參數:jps -v

結果:
這裏寫圖片描述

3. 通過jstack命令查看某個Java進程內的線程堆棧信息

3.1 輸出當前時刻,某進程內的線程堆棧信息:jstack -l [pid]

pid代表要查看的進程ID,可以通過前面的 jps -l 命令獲取。
結果:
這裏寫圖片描述
nid=0x7580 後面的信息代表當前時刻下線程的狀態。
在排查問題時,只根據“某1個時刻下的線程狀態”判斷程序問題,證據不足。通常會連續查看好幾個時刻下的線程狀態,這樣排查方向纔不會錯。

線程的狀態分析如下:
Runnable:該狀態表示線程具備所有運行條件,在運行隊列中準備操作系統的調度,或者正在運行。
Waiton condition:該狀態表示線程正在等待某個條件的發生。比如網絡讀寫的線程,由於網絡帶寬已被佔用光了,就會處於等待狀態;再比如處於sleep中的線程,當睡眠時間到了,線程纔會被喚醒。
Waiting for monitor entry 和 in Object.wait()
在多線程編程時,我們爲了避免多線程併發造成數據讀寫錯誤,通常會將一段代碼用同步代碼塊進行控制:

synchronized(myObject){ 
  //代碼塊....... 
} 

這樣,在某一時刻,只允許“擁有myObject對象鎖”的線程進入這個同步代碼塊。從而保證了數據讀寫的串行執行,避免產生錯誤。我們把這個同步代碼塊也叫做臨界區;臨界區裏需要串行讀寫的數據叫做互斥資源,或者叫做競爭資源。

如果在多線程的程序中,大量使用 synchronized,或者不適當的使用了它,會造成大量線程在臨界區的入口等待,造成系統的性能大幅下降。如果在線程 DUMP中發現了這個情況,應該審查源碼,改進程序。

當線程申請訪問某一臨界區,如果它獲得了“myObject的對象鎖”,他就可以進入臨界區了,這時線程狀態是Runnable。

當線程申請訪問某一臨界區,如果“myObject的對象鎖”已經被別的線程佔有,它需要等待對象鎖被釋放,這時線程狀態是waiting for monitor entry。

當線程申請訪問某一臨界區,並且它獲得了“myObject的對象鎖”,但是執行到臨界區的某處時,由於一些原因需要通過myObject.wait() 方法讓當前線程暫停下來(wait方法和notify方法的調用一定要在同步代碼塊中,並且只能使用對象鎖的實例對象的wait方法和notify方法),這時線程會釋放持有的對象鎖,狀態變爲in Object.wait()。直到某線程調用myObject.notify() 方法,將暫停的線程被喚醒,被喚醒的線程開始有權利再次申請對象鎖,在申請到對象鎖之前,狀態都是in Object.wait()的,申請到對象鎖之後,變爲運行狀態。

以截圖裏最後一個線程信息爲例,locked <…ddaa0> (ajava.util.ArrayList) 指當前線程持有了對象實例…ddaa0對象鎖。
waiting on <…ddaa0> (ajava.util.ArrayList) 指當前線程釋放了對象實例…ddaa0的對象鎖,處於等待狀態。

下週繼續:
如何查看遠程機器?
如何將線程棧信息保存爲文件?

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章