7屠升、虛擬機性能監(jiān)控與故障處理工具(2)(JVM筆記)

二、JDK的可視化工具

2.1 JConsole:Java監(jiān)視與管理控制臺

JConsole(Java Monitoring and Management Console)是一種基于JMX的可視化監(jiān)視汇在、管理工具脏答。它管理部分的功能是針對JMX MBean進行管理,由于MBean可以使用代碼阿蝶、中間件服務器的管理控制臺或者所有符合JMX規(guī)范的軟件進行訪問黄绩。

2.1.1 啟動JConsole

JDKbin目錄中可以直接雙擊運行此工具爽丹。

1

啟動后我們可以對其中一個進程進行監(jiān)控(這里我們只是啟動了JConsole進程)辛蚊,得到的監(jiān)控界面如下:
2

說明:“概述”頁面顯示的是整個虛擬機主要運行數(shù)據(jù)的概覽嚼隘,其中包括“對內存使用情況”袒餐、“線程”灸眼、“類”、“CPU使用情況”四種信息的曲線圖焰宣。

2.1.2 內存監(jiān)控

“內存”頁相當于可視化的jstat命令匕积,用于監(jiān)視受收集器管理的虛擬機內存(Java堆和永久代)的變化趨勢。這里通過例子說明(這里親自試驗了書中的例子闪唆,但是拿到的曲線和書中有點不一樣悄蕾,這里還是以書中為準):

代碼如下:

//使用java -Xms100m -Xmx100m -XX:+UseSerialGC運行
public static void main(String[] args) throws Exception{
    fileHeap(1000);
}

static class OOMObject{
    public byte[] placeholder = new byte[64 * 1024];

}

public static void fileHeap(int num) throws InterruptedException{

    List<OOMObject> list = new ArrayList<OOMObject>();
    for(int i = 0; i < num; i++){
        Thread.sleep(50);
        list.add(new OOMObject());
    }
    System.gc();
}

3

說明:這段代碼的作用是以64KB/50ms的速度往Java堆中填充數(shù)據(jù)帆调,一共填充1000次,使用JConsole的“內存”頁進行監(jiān)視含鳞,曲線變化如上圖芹务。這里可以看到,內存池Eden區(qū)的運行趨勢呈現(xiàn)折線狀潜必。監(jiān)視范圍擴大至整個堆后沃但,會發(fā)現(xiàn)曲線是一條向上增長的平滑曲線。之所以呈現(xiàn)折線是因為當Eden區(qū)被填滿時進行一次GC垂攘。從柱狀圖中可以看到,在1000次循環(huán)執(zhí)行結束吱型,運行了Sytem.gc()后陨仅,雖然整個新生代EdenSurvivor區(qū)都基本被清空了,但是代表老年代的柱狀圖仍然保持峰值狀態(tài)触徐,說明被填充進堆中的數(shù)據(jù)在System.gc()方法執(zhí)行后仍然存活狐赡。

  • 問題一:虛擬機啟動參數(shù)只限制了Java堆為100MB颖侄,沒有指定-Xmn參數(shù)(-Xms初始堆大小,-Xmx最大堆大行⑷怠)穴墅,能否從監(jiān)控圖中估計出新生代有多大?
    從圖中可以看到Eden空間為27328KB,因為沒有設置-XX:SurvivorRadio參數(shù)悼泌,所以EdenSurvivor空間比例默認為8:1馆里,整個新生代空間大約為27328KB*125%=34160KB

  • 問題二丙者、為何執(zhí)行了System.gc()之后营密,圖中代表的老年代的柱狀圖仍然顯示峰值狀態(tài),代碼需要如何改動才能讓System.gc()回收掉填充到堆中的對象纷捞?
    執(zhí)行完System.gc()后,空間未能回收是因為在List<OOMObject> list對象仍然存活奖唯,fileHeap()方法仍然沒有退出糜值,因此list對象在System.gc()執(zhí)行時仍然處于作用域之內。如果把System.gc()移動到fileHeap()方法外調用就可以回收掉全部內存病往。

2.1.3 線程監(jiān)控

如果上面的“內存”頁簽相當于可視化的jstat命令的話荣恐,“線程”頁簽的功能相當于可視化的jstack命令车要,遇到線程停頓時可以使用這個頁簽進行監(jiān)控分析寿弱。之前說過線程長時間停頓的主要原因主要有:等待外部資源(數(shù)據(jù)庫連接嚷硫、網絡資源仔掸、設備資源等)医清、死循環(huán)、鎖等待(活鎖和死鎖)负懦。下面通過代碼演示:

public static void createBusyThread(){
    Thread thread = new Thread(new Runnable(){
        @Override
        public void run(){
            while(true)
                ;
        }
    }, "testBusyThread");
    
    thread.start();
}

//線程鎖等待演示

public static void createLockThread(final Object lock){
    Thread thread = new Thread(new Runnable(){
        @Override
        public void run(){
            synchronized(lock){
                try{
                    lock.wait();
                } catch(InterruptedException e){
                    e.printStackTrace();
                }
            }
        }
    }, "testLockThread");
    thread.start();
}

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

說明:程序運行后纸厉,首先在“線程”頁簽中選擇main線程五嫂,如圖所示。堆棧追蹤顯示BufferedReaderreadBytes方法中等待System.in的鍵盤輸入抛猫,這時線程為Runnable狀態(tài)闺金,Runnable狀態(tài)的線程會被分配運行時間,但readBytes方法檢查到流沒有更新時會立刻歸還執(zhí)行令牌败匹,這種等待只消耗很小的CPU資源掀亩。

4

接著監(jiān)控testBusyThread線程,如圖所示捉蚤。此時處于一個死循環(huán)中炼七,不會歸還線程執(zhí)行令牌豌拙,會消耗很多CPU資源。

5

在執(zhí)行testLockThread線程時捉超,在等待著lock對象的nofifynotifyAll方法的出現(xiàn)唯绍,此時線程處于WAITTING狀態(tài)况芒,在被喚醒之前是不會被分配執(zhí)行時間的。

6

這個線程只要lock對象的notify()notifyAll()方法被調用就會被激活,繼續(xù)執(zhí)行皮壁。下面的代碼演示了無法再被激活的死鎖等待哪审。

//線程死鎖等待演示
static class SynAddRunalbe implements Runnable{
    int a , b;
    public SynAddRunalbe(int a, int b){
        this.a = a;
        this.b = b;
    }
    
    @Override
    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 SynAddRunalbe(1, 2)).start();
        new Thread(new SynAddRunalbe(2, 1)).start();
    }
}

說明:這段代碼開了200個線程去分別計算1+2以及2+1的值,一般的話舌狗,for循環(huán)只需要運行2~3次就會遇到線程死鎖扔水,程序無法結束。造成死鎖的原因是Integer.valueOf()方法基于減少對象創(chuàng)建次數(shù)和節(jié)省內存的考慮主届,[-128, 127]之間的數(shù)字會被緩存待德,當valueOf()方法傳入參數(shù)在這個范圍之內将宪,將直接返回緩存中的對象。即代碼中調用了200valueOf()方法一共就只返回了兩個不同的對象印蔗。加入在某個線程的兩個synchronized塊之間發(fā)生了一次線程切換燎潮,那就會出現(xiàn)線程A等著被線程B持有的Integer.valueOf(1),線程B又等著被線程A持有的Integer.valueOf(2)除呵,結果出現(xiàn)大家都拋不下去的情景爪喘。

出現(xiàn)死鎖之后秉剑,點擊JConsole線程面板的“監(jiān)測到死鎖”的按鈕,將出現(xiàn)一個新的“死鎖”頁簽诡曙,如圖所示略水。

7

從圖中可以看到渊涝,線程Thread-43在等待一個被線程Thread-12持有的Integer對象床嫌,而點擊線程Thread-12則顯示它也在等待一個Integer對象胸私,被線程Thread-43持有岁疼,這樣就發(fā)生了死鎖。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末洒敏,一起剝皮案震驚了整個濱河市疙驾,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌函荣,老刑警劉巖扳肛,帶你破解...
    沈念sama閱讀 217,185評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件挖息,死亡現(xiàn)場離奇詭異,居然都是意外死亡绪抛,警方通過查閱死者的電腦和手機电禀,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評論 3 393
  • 文/潘曉璐 我一進店門尖飞,熙熙樓的掌柜王于貴愁眉苦臉地迎上來政基,“玉大人,你說我怎么就攤上這事沮明∩豪蓿” “怎么了?”我有些...
    開封第一講書人閱讀 163,524評論 0 353
  • 文/不壞的土叔 我叫張陵圣贸,是天一觀的道長扛稽。 經常有香客問我在张,道長,這世上最難降的妖魔是什么啄骇? 我笑而不...
    開封第一講書人閱讀 58,339評論 1 293
  • 正文 為了忘掉前任瘟斜,我火速辦了婚禮螺句,結果婚禮上,老公的妹妹穿的比我還像新娘芽唇。我一直安慰自己取劫,他們只是感情好,可當我...
    茶點故事閱讀 67,387評論 6 391
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著虾标,像睡著了一般。 火紅的嫁衣襯著肌膚如雪傀蚌。 梳的紋絲不亂的頭發(fā)上蘸吓,一...
    開封第一講書人閱讀 51,287評論 1 301
  • 那天库继,我揣著相機與錄音,去河邊找鬼艺谆。 笑死,一個胖子當著我的面吹牛琅催,可吹牛的內容都是我干的虫给。 我是一名探鬼主播抹估,決...
    沈念sama閱讀 40,130評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼嫁佳!你這毒婦竟也來了谷暮?” 一聲冷哼從身側響起湿弦,我...
    開封第一講書人閱讀 38,985評論 0 275
  • 序言:老撾萬榮一對情侶失蹤颊埃,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后班利,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 45,420評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,617評論 3 334
  • 正文 我和宋清朗相戀三年彻消,在試婚紗的時候發(fā)現(xiàn)自己被綠了宙拉。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,779評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡御板,死狀恐怖崔步,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤瑞你,帶...
    沈念sama閱讀 35,477評論 5 345
  • 正文 年R本政府宣布希痴,位于F島的核電站,受9級特大地震影響砌创,放射性物質發(fā)生泄漏虏缸。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,088評論 3 328
  • 文/蒙蒙 一嫩实、第九天 我趴在偏房一處隱蔽的房頂上張望刽辙。 院中可真熱鬧,春花似錦甲献、人聲如沸宰缤。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,716評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽慨灭。三九已至,卻和暖如春球及,著一層夾襖步出監(jiān)牢的瞬間氧骤,已是汗流浹背吃引。 一陣腳步聲響...
    開封第一講書人閱讀 32,857評論 1 269
  • 我被黑心中介騙來泰國打工筹陵, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人际歼。 一個月前我還...
    沈念sama閱讀 47,876評論 2 370
  • 正文 我出身青樓惶翻,卻偏偏與公主長得像,于是被迫代替她去往敵國和親鹅心。 傳聞我的和親對象是個殘疾皇子吕粗,可洞房花燭夜當晚...
    茶點故事閱讀 44,700評論 2 354

推薦閱讀更多精彩內容