虛擬機(jī)性能監(jiān)控與故障處理工具

在JDK的bin目錄下巍耗,可以看到很多工具秋麸,這些工具的程序體積都異常小巧【嫣基本都穩(wěn)定在17K左右灸蟆。這并非JDK開發(fā)團(tuán)隊刻意把他們制作得如此精煉,而是這些命令行工具大多數(shù)是JDK/lib/tools.jar類庫的一層薄包裝而已娄琉,它們主要的功能代碼是在tools類庫中實(shí)現(xiàn)的次乓。
之所以這樣做,是因?yàn)楫?dāng)應(yīng)用程序部署到生產(chǎn)環(huán)境后孽水,無論是直接接觸物理服務(wù)器還是遠(yuǎn)程Telnet到服務(wù)器上都可能會受到限制票腰。借助tools.jar類庫里面的接口,我們可以直接在應(yīng)用程序中實(shí)現(xiàn)功能強(qiáng)大的監(jiān)控分析功能女气。

下面列舉JDK主要命令行監(jiān)控工具的用途杏慰。


image.png

image.png

1.jps:虛擬機(jī)就進(jìn)程狀況工具

  • JDK的很多小工具的名字都參考了UNIX命令的命名方式,jps名字像UNIX的ps命令之外炼鞠,也和ps命令類似:可以列出正在運(yùn)行的虛擬機(jī)進(jìn)程缘滥。并顯示虛擬機(jī)執(zhí)行主類(Main Class,main()函數(shù)所在的類)名稱以及這些進(jìn)程的本地虛擬機(jī)唯一ID(Local Virtual Machine Identifier,LVMID)。
  • 雖然功能比較單一谒主,但它是使用頻率最高的JDK命令行工具朝扼,因?yàn)槠渌腏DK工具大多需要輸入它查詢到的LVMID來確定要監(jiān)控的是哪一個虛擬機(jī)進(jìn)程。對于本地虛擬機(jī)進(jìn)程來說霎肯,LVMID與操作系統(tǒng)的進(jìn)程ID是一致的擎颖。使用Windows的任務(wù)管理器或者UNIX的ps命令也可以
  • 查詢到虛擬機(jī)進(jìn)程的LVMID榛斯,但如果同時啟動多個虛擬機(jī)進(jìn)程,無法根據(jù)進(jìn)程名稱定位時搂捧,那只有依賴jps命令顯示主類的功能才能區(qū)分了驮俗。

jps命令格式如下:

image

現(xiàn)在我們打開一個eclispe,寫一段程序允跑,例子如下:

package hjc.test9a;

import java.util.Scanner;

/**
 * Created by cong on 2018/4/5.
 */
public class Main {

    public Main() {
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        sc.next();
    }

}

連續(xù)運(yùn)行2次王凑,打開cmd,再用jps查看,如下:


image.png

2.jstat:虛擬機(jī)統(tǒng)計信息監(jiān)控工具

jstat(JVM Statistics Monitoring Tool)是用于監(jiān)控虛擬機(jī)各種運(yùn)行狀態(tài)信息的命令行工具聋丝。它可以顯示本地或者遠(yuǎn)程虛擬機(jī)進(jìn)程中的類裝載索烹,內(nèi)存,垃圾收集潮针,JIT編譯等運(yùn)行數(shù)據(jù)术荤。
\color{red}{在沒有GUI圖形界面,只提供了純文本控制臺環(huán)境的服務(wù)器上每篷,它將是運(yùn)行期定位虛擬機(jī)性能問題的首選工具瓣戚。}

jstat命令格式為:

jstat [ option vmid [interval [s|ms] [count]] ]

對于命令格式中的VMID與LVMID需要特別說明一下:如果是本地虛擬機(jī)進(jìn)程,VMID與LVMID是一致的焦读,如果是遠(yuǎn)程虛擬機(jī)進(jìn)程子库,那VMID的格式應(yīng)當(dāng)是:

image

參數(shù)interval 和count代表查詢間隔和次數(shù),如果省略這兩個參數(shù)矗晃,說明只查詢一次仑嗅。假設(shè)要美250毫秒查詢一次進(jìn)程2764垃圾收集情況,一個查詢20次张症,那命令應(yīng)當(dāng)是:

jstat -gc 2764 250 20

選項(xiàng)option代表著用戶希望查詢的虛擬機(jī)信息仓技,主要分為3類:類裝載,垃圾收集俗他,運(yùn)行期編譯狀況脖捻,具體選項(xiàng)及作用請參考如下列表:

image

jstat 監(jiān)控選項(xiàng)眾多,這里僅舉一個例子演示如何查看監(jiān)控結(jié)果兆衅。繼續(xù)運(yùn)行上面的例子如下:

image

3.jinfo:Java配置信息工具

  • jinfo(Configuration Info for Java) 的作用是實(shí)時地查看和調(diào)整虛擬機(jī)各項(xiàng)參數(shù)地沮。使用jps命令的-v參數(shù)可以查看虛擬機(jī)啟動時顯式指定的參數(shù)列表,但如果想知道未被顯式指定的參數(shù)的系統(tǒng)默認(rèn)值羡亩,除了去找資料摩疑,就只能使用jinfo的-flag選項(xiàng)進(jìn)行查詢了
  • (如果只限于JDK1.6或以上版本的話,使用java -XX:+PrintFlagsFianl查看參數(shù)默認(rèn)值也是一個很好的選擇)畏铆,jinfo還可以使用-sysprops選項(xiàng)把虛擬機(jī)進(jìn)程的System.getProperties()的內(nèi)容打印出來雷袋。這個命令在JDK1.5時期已經(jīng)伴隨Linux的JDK發(fā)布,當(dāng)時只提供了信息查詢的功能辞居,
  • JDK1.6之后片排,jinfo在Windows和Linux平臺都有提供寨腔,并且加入了運(yùn)行期修改參數(shù)的能力,可以使用-flag [+|-] name或者 -flag name=value 修改一部分運(yùn)行期可寫的虛擬機(jī)參數(shù)值率寡。JDK1.6中,jinfo對于Windows平臺功能仍然有很大的限制倚搬,只提供了最基本的-flag選項(xiàng)冶共。

jinfo的命令格式如下:

jinfo [option] pid

image

4.jmap:Java內(nèi)存映像工具

  • jmap命令用于生成堆轉(zhuǎn)儲快照(一般稱為heapdump 或者dump文件),如果不是用jmap命令,想要獲取Java堆轉(zhuǎn)儲快照每界,要有一些暴力手段捅僵,
  • 用-XX:HeapDumpOnOutOfMemoryError參數(shù),可以讓虛擬機(jī)在OOM異常出現(xiàn)之后自動生成dump文件眨层,
  • 通過-XX:HeapDumpOnCtrlBreak參數(shù)則可以使用[Ctrl]+[Break]鍵讓虛擬機(jī)生成dump文件庙楚,又或者在Linux系統(tǒng)下通過Kill -3命令發(fā)送進(jìn)程退出信號嚇唬一下虛擬機(jī),也能拿到dump文件趴樱。
  • jmap的作用并不僅僅是為了獲取dump文件馒闷,它還可以查詢finalize執(zhí)行隊列,java堆和永久代的詳細(xì)信息叁征,如空間使用率纳账,當(dāng)前用的是哪種收集器等。

jmap有不少功能在Windows平臺下都是受限制的捺疼,除了生成dump文件的-dump選項(xiàng)和用于查看每個類的實(shí)例疏虫,空間占用統(tǒng)計的-histo選項(xiàng)在所有操作系統(tǒng)都提供外,其余只能在Linux/Solaris下使用啤呼。

jmap命令格式:

jmap [option] vmid

option選項(xiàng)合法值與具體含義如下:

image

例子如下:

image
image
image

5.jhat:虛擬機(jī)堆轉(zhuǎn)儲快照分析工具

jhat命令與jmap搭配使用卧秘,來分析jmap生成的堆轉(zhuǎn)儲快照。jhat內(nèi)置了一個微型的HTTP/HTML服務(wù)器官扣,生成dump文件的分析結(jié)果后翅敌,可以在瀏覽器查看。實(shí)際工作中醇锚,如果沒有別的工具可用哼御,一般不會用jhat分析dump文件的。

原因有二:一是一般不會在部署應(yīng)用程序的服務(wù)器上直接分析dump文件焊唬,即使這樣做恋昼,也會盡量將dump文件復(fù)制到其他機(jī)器上進(jìn)行分析,因?yàn)榉治龉ぷ魇且粋€耗時并且消耗硬件資源的過程赶促。另外一個原因是jhat的分析功能相對于簡陋液肌,

后面會提到專業(yè)的工具VisualVM,以及專業(yè)分析dump的Eclispe Memory Analyzer鸥滨,等工具嗦哆。

image
image
image

6.jstack:Java堆棧跟蹤工具

  • jstack命令用于生成虛擬機(jī)當(dāng)前時刻的線程快照(一般稱為threaddump或者javacore文件)谤祖。線程快照就是當(dāng)前虛擬機(jī)內(nèi)每一條線程正在執(zhí)行的方法堆棧集合,生成線程快照的主要目的是定位線程出現(xiàn)長時間停頓的原因老速。
  • 線程出現(xiàn)停頓的時候通過jstack來查看各個線程的調(diào)用堆棧粥喜,就可以知道沒有響應(yīng)的線程到底在后臺做些什么事情,或者等待著什么資源

jstack命令格式如下:

jstack [option] vmid

option選項(xiàng)的合法值與具體含義如下:

image

例子如下:

image

在JDK1.5中橘券,java.lang.Thread類新增了一個getAllStackTraces()方法用于獲取虛擬機(jī)中所有線程的StackTraceElement對象额湘。使用這個方法可以通過簡單的幾行代碼就完成了jstack的大部分功能。在實(shí)際項(xiàng)目中不妨調(diào)用這個方法做個管理員頁面旁舰,可以隨時使用瀏覽器

來查看線程堆棧锋华,例子如下:

package hjc.test9b;

import java.util.Map;

/**
 * Created by cong on 2018/4/5.
 */
public class Main {
    public static void main(String[] args) {
        Map<Thread, StackTraceElement[]> m = Thread.getAllStackTraces();

        for (Map.Entry<Thread, StackTraceElement[]> en : m.entrySet()){
            Thread t = en.getKey();
            StackTraceElement[] v = en.getValue();

            System.out.println("The Thread name is :" + t.getName());
            for (StackTraceElement s : v){
                System.err.println("\t" + s.toString());
            }
        }

    }
}

運(yùn)行結(jié)果如下:

image

7.JConsole:Java監(jiān)控與管理控制平臺。

JConsole是一種基于JMX的可視化監(jiān)視箭窜,管理工具毯焕。通過JDK/bin目錄下的jconsole.exe來啟動JConsole

image

雙機(jī)進(jìn)去,可以看到主界面包括概述磺樱,內(nèi)存纳猫,線程,類坊罢,VM摘要续担,MBean6個頁面

image

對線程的監(jiān)控例子如下:
死循環(huán)演示:

    /**
     * 線程死循環(huán)演示
     */
    public static void createBusyThread() {
        Thread thread = new Thread(new Runnable() {
            public void run() {
                while (true)
                    ;
            }
        }, "testBusyThread");
        thread.start();
    }

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        br.readLine();
        createBusyThread();
    }
    

線程鎖等待演示:

/**
     * 線程鎖等待演示
     */
    public static void createLockThread(final Object lock) {
        Thread thread = new Thread(new Runnable() {
            public void run() {
                synchronized (lock) {
                    try {
                        lock.wait();
                    }catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }, "testLockThread");
        thread.start();
    }
    
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        br.readLine();
        Object obj = new Object();
        createLockThread(obj);
    }
image
image
image
image

死鎖代碼樣例:

public class SynAddRunable implements Runnable {
    int a, b;
    public SynAddRunable(int a, int b) {
        this.a = a;
        this.b = b;
    }
    
    public void run() {
        synchronized (Integer.valueOf(a)) {
            synchronized (Integer.valueOf(b)) {
                System.out.println(a + b);
            }
        }
    }
    
    public static void main(String[] args) {
        for ( int i = 0; i < 100; i++) {
            new Thread(new SynAddRunable(1, 2)).start();
            new Thread(new SynAddRunable(2, 1)).start();
        }
    }
}

這段代碼開了200個線程去分別計算1+2以及2+1的值,造成死鎖的原因是Integer.valueOf()方法基于減少對象創(chuàng)建次數(shù)和節(jié)省內(nèi)存的考慮活孩,[-128,127]之間的數(shù)字會被緩存物遇,當(dāng)valueOf()方法傳入?yún)?shù)在這個范圍之內(nèi),將直接返回緩存中的對象憾儒。也就是說

代碼中調(diào)用200次Integer.valueOf()方法一共就返回了兩個不同的對象询兴。假如在某個線程的兩個synchronized塊之間發(fā)生了一次線程切換,那就會出現(xiàn)線程A等線程B持有的Integer.valueOf(1),線程B又等待著被線程A持有的Integer.valueOf(2),結(jié)果大家都跑不下去起趾。

出現(xiàn)死鎖后诗舰,點(diǎn)擊Jconsole線程面板的檢測到死鎖的按鈕,將出現(xiàn)一個新的死鎖標(biāo)簽训裆。如下圖:

image

8.VisualVM:多合一故障處理工具

VisualVM可以做到:
1.顯示虛擬機(jī)繼承以及進(jìn)程的配置眶根,環(huán)境信息(jps,jinfo)
2.監(jiān)視應(yīng)用程序的CPU,GC,堆,方法區(qū)边琉,以及線程信息(jstack,jstat)
3.dump以及分析堆轉(zhuǎn)快照(jmap属百,jhat)
4.方法級的程序運(yùn)行性能分析,找出被調(diào)用最多变姨,運(yùn)行時間最長的方法族扰。
5.離線程序快照:收集程序的運(yùn)行時配置,線程dump,內(nèi)存dump等信息建立一個快照渔呵,可以將快照發(fā)送開發(fā)者進(jìn)行BUG反饋怒竿。

image

安裝后,打開如下:

image

轉(zhuǎn)載自:
https://www.cnblogs.com/huangjuncong/p/8995333.html

Btrace參考:
基于Btrace的監(jiān)控調(diào)試
https://blog.51cto.com/zero01/2143096

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末扩氢,一起剝皮案震驚了整個濱河市耕驰,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌录豺,老刑警劉巖耍属,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異巩检,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)示启,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進(jìn)店門兢哭,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人夫嗓,你說我怎么就攤上這事迟螺。” “怎么了舍咖?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵矩父,是天一觀的道長。 經(jīng)常有香客問我排霉,道長窍株,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任攻柠,我火速辦了婚禮球订,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘瑰钮。我一直安慰自己冒滩,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布浪谴。 她就那樣靜靜地躺著开睡,像睡著了一般。 火紅的嫁衣襯著肌膚如雪苟耻。 梳的紋絲不亂的頭發(fā)上篇恒,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天,我揣著相機(jī)與錄音梁呈,去河邊找鬼婚度。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的蝗茁。 我是一名探鬼主播醋虏,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼哮翘!你這毒婦竟也來了颈嚼?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤饭寺,失蹤者是張志新(化名)和其女友劉穎阻课,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體艰匙,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡限煞,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了员凝。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片署驻。...
    茶點(diǎn)故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖健霹,靈堂內(nèi)的尸體忽然破棺而出旺上,到底是詐尸還是另有隱情,我是刑警寧澤糖埋,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布宣吱,位于F島的核電站,受9級特大地震影響瞳别,放射性物質(zhì)發(fā)生泄漏征候。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一洒试、第九天 我趴在偏房一處隱蔽的房頂上張望倍奢。 院中可真熱鬧,春花似錦垒棋、人聲如沸卒煞。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽畔裕。三九已至,卻和暖如春乖订,著一層夾襖步出監(jiān)牢的瞬間扮饶,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工乍构, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留甜无,地道東北人。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像岂丘,于是被迫代替她去往敵國和親陵究。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評論 2 354