使用Java工具解決生產(chǎn)故障(二)- 內(nèi)存泄漏及OOM異常分析

1.工具準(zhǔn)備

本章節(jié)除了用到上一章提到的jcmd之外,還會(huì)使用到VisualVM工具。此工具在JDK安裝目錄\bin下,文件名為jvisualvm荧缘。你也可以在
http://visualvm.github.io/download.html
下載到最新的版本。

VisualVM使用各種技術(shù)(包括jvmstat拦宣,JMX胜宇,Serviceability Agent(SA)和Attach API)來進(jìn)行故障定位耀怜。至少需要具備JDK的版本1.4+。

我使用的是上述鏈接中下載的jvisualvm1.4版本桐愉。
官方中文教程:
http://visualvm.github.io/documentation.html

建議:將etc下visualvm配置文件中的-Xmx最大堆內(nèi)存的大小調(diào)大一些财破,否則在加載dump文件過程中很容易發(fā)生oom。

2.故障模擬

今天我們要模擬的故障是一種常見的內(nèi)存泄漏从诲。源代碼如下:

package com.brianxia.error;

import java.util.HashMap;
import java.util.Map;
import java.util.Random;

public class MemoryLeak {

    //存儲(chǔ)內(nèi)存泄漏的數(shù)據(jù)
    public static Map<String, String> data = new HashMap<>();

    public static void addData(String key) {

        data.put(key, "");
    }

    public static void deleteData(String key) {

        data.remove(key, "");
    }

    public static void throwEx() throws Exception {
        throw new RuntimeException("leak");

    }

    //內(nèi)存泄漏代碼左痢,添加數(shù)據(jù)之后拋出異常,從而無法執(zhí)行刪除數(shù)據(jù)的代碼系洛,造成內(nèi)存泄漏的現(xiàn)象
    public static void leak() throws Exception {
        Random random = new Random();
        String key = String.valueOf(random.nextInt());
        addData(key);

        throwEx();

        deleteData(key);

    }

    public static void main(String[] args) {

        while (true) {
            try {
                leak();
                Thread.sleep(100);
            } catch (Exception e) {
                if (!(e instanceof RuntimeException))
                    e.printStackTrace();
            }
        }

    }

}

這是一段最簡單的內(nèi)存泄漏代碼俊性,本意是在leak函數(shù)中,通過add和delete描扯,回收掉添加到hashmap中的數(shù)據(jù)定页,但是在執(zhí)行add和delete的中間發(fā)生了異常,所以代碼路經(jīng)直接會(huì)跑到main函數(shù)中的異常捕獲中绽诚,從而hashmap中的數(shù)據(jù)永遠(yuǎn)不會(huì)被回收了典徊。

3.故障分析

關(guān)于如何識(shí)別是否有內(nèi)存泄漏,不在本文討論范疇內(nèi)恩够,后續(xù)會(huì)更新相應(yīng)的文章卒落。首先我們用上一次提到的jcmd來生成dump文件。

g>jcmd 6172 GC.heap_dump d:\dump_leak
6172:
Heap dump file created

打開visualvm蜂桶,選擇load剛才生成的文件儡毕。

Image 1.png

選擇Objects,查看下目前JVM中的對象狀態(tài)扑媚。

Image 2.png
Image 3.png

從上圖中可以看到腰湾,我們的代碼產(chǎn)生了非常多的對象,其中主要是char[]疆股、Hashmap的Node檐盟、String。那么這個(gè)時(shí)候我們就需要根據(jù)我們的項(xiàng)目具體進(jìn)行分析了押桃,首先我們的代碼中存在HashMap, key的數(shù)據(jù)類型是String导犹,而String的底層實(shí)現(xiàn)又是char[]唱凯,這三個(gè)的數(shù)量可以看到基本一致。
從上面的信息我們可以推斷出谎痢,我們代碼實(shí)現(xiàn)中存在內(nèi)存泄漏(當(dāng)然也有可能是未進(jìn)行GC磕昼,因?yàn)槭茄菔居美覀兛梢栽趘isualvm上手動(dòng)執(zhí)行GC)节猿。

image.png

點(diǎn)開詳細(xì)的Object列表票从,可以看到相關(guān)的reference信息漫雕。從上圖可以知道,我們的Hashmap Node主要是在MemoryLeak類中的static變量data中被引用到峰鄙,無法得到釋放浸间。
之后就需要各位小伙伴去查驗(yàn)整個(gè)變量的生命周期,確認(rèn)為何資源沒有被回收吟榴。

4.總結(jié)

以上就是基本的生產(chǎn)下處理問題的流程魁蒜,需要注意的是,生產(chǎn)上可以打開

-XX:+HeapDumpOnOutOfMemoryError 
-XX:HeapDumpPath=${目錄} 

這兩個(gè)參數(shù)吩翻,讓發(fā)生OOM的時(shí)候自動(dòng)生成dump用于后續(xù)分析兜看。當(dāng)然最好的情況是在測試環(huán)境中能夠通過分析heap信息發(fā)現(xiàn)問題,而不是到生產(chǎn)上再去解決狭瞎。
下一章中细移,我會(huì)講解JVM內(nèi)存的基本原理及如何分析內(nèi)存狀態(tài)。

作者:BrianXia
轉(zhuǎn)載請注明 http://www.reibang.com/p/065d12dd3e44

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末熊锭,一起剝皮案震驚了整個(gè)濱河市弧轧,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌球涛,老刑警劉巖劣针,帶你破解...
    沈念sama閱讀 216,470評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異亿扁,居然都是意外死亡捺典,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,393評論 3 392
  • 文/潘曉璐 我一進(jìn)店門从祝,熙熙樓的掌柜王于貴愁眉苦臉地迎上來襟己,“玉大人,你說我怎么就攤上這事牍陌∏嬖。” “怎么了?”我有些...
    開封第一講書人閱讀 162,577評論 0 353
  • 文/不壞的土叔 我叫張陵毒涧,是天一觀的道長贮预。 經(jīng)常有香客問我,道長契讲,這世上最難降的妖魔是什么仿吞? 我笑而不...
    開封第一講書人閱讀 58,176評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮捡偏,結(jié)果婚禮上唤冈,老公的妹妹穿的比我還像新娘。我一直安慰自己银伟,他們只是感情好你虹,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,189評論 6 388
  • 文/花漫 我一把揭開白布绘搞。 她就那樣靜靜地躺著,像睡著了一般傅物。 火紅的嫁衣襯著肌膚如雪夯辖。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,155評論 1 299
  • 那天挟伙,我揣著相機(jī)與錄音楼雹,去河邊找鬼。 笑死尖阔,一個(gè)胖子當(dāng)著我的面吹牛贮缅,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播介却,決...
    沈念sama閱讀 40,041評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼谴供,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了齿坷?” 一聲冷哼從身側(cè)響起桂肌,我...
    開封第一講書人閱讀 38,903評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎永淌,沒想到半個(gè)月后崎场,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,319評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡遂蛀,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,539評論 2 332
  • 正文 我和宋清朗相戀三年谭跨,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片李滴。...
    茶點(diǎn)故事閱讀 39,703評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡螃宙,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出所坯,到底是詐尸還是另有隱情谆扎,我是刑警寧澤,帶...
    沈念sama閱讀 35,417評論 5 343
  • 正文 年R本政府宣布芹助,位于F島的核電站堂湖,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏状土。R本人自食惡果不足惜无蜂,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,013評論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望声诸。 院中可真熱鬧,春花似錦退盯、人聲如沸彼乌。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,664評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽慰照。三九已至灶挟,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間毒租,已是汗流浹背稚铣。 一陣腳步聲響...
    開封第一講書人閱讀 32,818評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留墅垮,地道東北人惕医。 一個(gè)月前我還...
    沈念sama閱讀 47,711評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像算色,于是被迫代替她去往敵國和親抬伺。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,601評論 2 353