記一次Java服務(wù)頻繁Full GC的排查過程

現(xiàn)象

從監(jiān)控來看娩嚼,堆內(nèi)存是夠用的,但是頻繁觸發(fā)Full GC腐泻,每秒鐘三次,每次耗時(shí)三四秒队询。

image.png

結(jié)合Young GC的信息和堆內(nèi)存的使用情況派桩,可以發(fā)現(xiàn)新生代的內(nèi)存夠用,老生代的內(nèi)存不夠用蚌斩,頻繁Full GC铆惑,老生代的內(nèi)存使用率依舊達(dá)到了98%。

2018-11-20T15:02:46.002+0800: 2779214.232: [GC2018-11-20T15:02:46.002+0800: 2779214.232: [ParNew: 1643604K->4513K(1843200K), 0.0129920 secs] 4994360K->3355569K(5257216K), 0.0131040 secs] [Times: user=0.05 sys=0.00, real=0.01 secs]
$ sudo jmap -heap 11927
Attaching to process ID 11927, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 24.65-b04-internal

using parallel threads in the new generation.
using thread-local object allocation.
Concurrent Mark-Sweep GC

Heap Configuration:
   MinHeapFreeRatio = 40
   MaxHeapFreeRatio = 70
   MaxHeapSize      = 5593104384 (5334.0MB)
   NewSize          = 2097152000 (2000.0MB)
   MaxNewSize       = 2097152000 (2000.0MB)
   OldSize          = 5439488 (5.1875MB)
   NewRatio         = 2
   SurvivorRatio    = 8
   PermSize         = 536870912 (512.0MB)
   MaxPermSize      = 536870912 (512.0MB)
   G1HeapRegionSize = 0 (0.0MB)

Heap Usage:
New Generation (Eden + 1 Survivor Space):
   capacity = 1887436800 (1800.0MB)
   used     = 899619040 (857.9435729980469MB)
   free     = 987817760 (942.0564270019531MB)
   47.66353183322482% used
Eden Space:
   capacity = 1677721600 (1600.0MB)
   used     = 895864384 (854.3628540039062MB)
   free     = 781857216 (745.6371459960938MB)
   53.39767837524414% used
From Space:
   capacity = 209715200 (200.0MB)
   used     = 3754656 (3.580718994140625MB)
   free     = 205960544 (196.41928100585938MB)
   1.7903594970703125% used
To Space:
   capacity = 209715200 (200.0MB)
   used     = 0 (0.0MB)
   free     = 209715200 (200.0MB)
   0.0% used
concurrent mark-sweep generation:
   capacity = 3495952384 (3334.0MB)
   used     = 3432530640 (3273.516311645508MB)
   free     = 63421744 (60.48368835449219MB)
   98.18585217892945% used
Perm Generation:
   capacity = 536870912 (512.0MB)
   used     = 52807616 (50.36126708984375MB)
   free     = 484063296 (461.63873291015625MB)
   9.836184978485107% used

28784 interned Strings occupying 3175392 bytes.

排查過程

這種現(xiàn)象表明送膳,服務(wù)存在內(nèi)存泄露员魏,所以需要分析堆的使用。使用gcore產(chǎn)生core文件叠聋,這比直接使用jmap dump快得多撕阎,可以避免對(duì)線上服務(wù)造成影響。core文件的大小跟進(jìn)程使用的堆大小一樣大碌补。

$ sudo gcore 11927
[Thread debugging using libthread_db enabled]
[New Thread 0x487ac940 (LWP 1653)]
[New Thread 0x486ab940 (LWP 1652)]
[New Thread 0x485aa940 (LWP 1651)]
0x00000030f0e07ba5 in pthread_join () from /lib64/libpthread.so.0

Saved corefile core.11927

使用jmap將core文件轉(zhuǎn)換成bin文件虏束。hprof文件跟進(jìn)程實(shí)際使用的堆內(nèi)存一樣大棉饶。

$sudo jmap -dump:format=b,file=heap.hprof.bin /opt/taobao/java/bin/java core.11927
Attaching to core core.11927 from executable /opt/taobao/java/bin/java, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 24.65-b04-internal
Dumping heap to heap.hprof.bin ...

這個(gè)轉(zhuǎn)換過程非常慢。將5.3GB的core轉(zhuǎn)換成4GB的hprof文件镇匀,花了將近半個(gè)小時(shí)照藻。通過top來看,這個(gè)dump是單線程做的汗侵,一直跑滿了一個(gè)核幸缕。

top - 15:43:38 up 214 days,  1:02,  2 users,  load average: 1.69, 1.83, 1.56
Tasks: 142 total,   1 running, 141 sleeping,   0 stopped,   0 zombie
Cpu(s): 51.5%us,  0.8%sy,  0.0%ni, 47.7%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Mem:   8194164k total,  8135628k used,    58536k free,    75324k buffers
Swap:        0k total,        0k used,        0k free,   797688k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
11927 www       20   0 6513m 5.3g  82m S 105.5 67.4  10760:36 java
 3764 root      20   0 2458m 791m  12m S 100.5  9.9  18:53.36 jmap
16376 root      20   0  411m 360m 1468 S  0.0  4.5  19:52.15 syslog-ng
11190 agent     20   0  540m 143m 5832 S  0.0  1.8  65:14.77 java

接著就是如何分析這個(gè)hprof文件的問題。目前主流的分析工具晰韵,有MAT和jhat发乔,下面分別使用二者分析一下。

jhat

jhat看起來比較簡(jiǎn)單宫屠,從分析結(jié)果里面可以看出用戶自定義類中列疗,SlsRecordWriter類的對(duì)象比較多,再做進(jìn)一步的分析就不知如何下手了浪蹂。

image.png
image.png

MAT

MAT體驗(yàn)比較好抵栈,直接分析出持有內(nèi)存最大的類,然后從dominator_tree里面可以看到具體的應(yīng)用情況坤次,可以發(fā)現(xiàn)SlsRecordWriter對(duì)象很多古劲。需要注意的是,使用MAT分析大的dump文件很吃內(nèi)存缰猴,所以需要調(diào)大堆內(nèi)存产艾。Mac上Eclipse的配置文件路徑是/Applications/Eclipse.app/Contents/Eclipse/eclipse.ini

image.png
image.png

結(jié)論

構(gòu)造一個(gè)demo驗(yàn)證一下滑绒。下面這個(gè)例子闷堡,運(yùn)行一段時(shí)間便會(huì)觸發(fā)Young GC(IDEA VM options設(shè)置上"-verbose:gc -XX:+PrintGCDetails"),但是從來不會(huì)調(diào)用Foo的finalize方法疑故,只有停止運(yùn)行的時(shí)候杠览,才會(huì)進(jìn)入hook執(zhí)行,接著釋放對(duì)象纵势。如果注釋掉addShutdownHook這段代碼踱阿,就符合期望了。所以addShutdownHook會(huì)導(dǎo)致Runtime持有對(duì)象钦铁,需要注意使用場(chǎng)景软舌。

class Foo {

    private String bar = new String("fdsaflkjdsalfjldsajflsajfoiwefnaslfjlaskejfowieajfalfjelajfieslkjflksdajlf");

    private int num = 0;

    public Foo() {
    }

    public Foo(int num) {

        System.out.println(String.format("Foo initialize: %d", num));

        this.num = num;

        Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
            public void run() {
                clean();
            }
        }));
    }

    void clean() {

        System.out.println(String.format("Foo clean: %d", num));
    }

    @Override
    protected void finalize() throws Throwable {
        super.finalize();

        System.out.println(String.format("foo finalize: %d", this.num));
    }
}

public class Demo {

    public static void main(String[] args) {

        int num = 0;

        while (true) {
            try {
                Foo foo = new Foo(num);
                num += 1;
                Thread.sleep(100);
            }catch (Exception e) {

            }
        }
    }
}

參考資料

  1. 阿里巴巴JDK故障排查指南
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市牛曹,隨后出現(xiàn)的幾起案子佛点,更是在濱河造成了極大的恐慌,老刑警劉巖黎比,帶你破解...
    沈念sama閱讀 207,113評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件恋脚,死亡現(xiàn)場(chǎng)離奇詭異腺办,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)糟描,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門怀喉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人船响,你說我怎么就攤上這事躬拢。” “怎么了见间?”我有些...
    開封第一講書人閱讀 153,340評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵聊闯,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我米诉,道長(zhǎng)菱蔬,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,449評(píng)論 1 279
  • 正文 為了忘掉前任史侣,我火速辦了婚禮拴泌,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘惊橱。我一直安慰自己蚪腐,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評(píng)論 5 374
  • 文/花漫 我一把揭開白布税朴。 她就那樣靜靜地躺著回季,像睡著了一般。 火紅的嫁衣襯著肌膚如雪正林。 梳的紋絲不亂的頭發(fā)上泡一,一...
    開封第一講書人閱讀 49,166評(píng)論 1 284
  • 那天,我揣著相機(jī)與錄音觅廓,去河邊找鬼瘾杭。 笑死,一個(gè)胖子當(dāng)著我的面吹牛哪亿,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播贤笆,決...
    沈念sama閱讀 38,442評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼蝇棉,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了芥永?” 一聲冷哼從身側(cè)響起篡殷,我...
    開封第一講書人閱讀 37,105評(píng)論 0 261
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎埋涧,沒想到半個(gè)月后板辽,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體奇瘦,經(jīng)...
    沈念sama閱讀 43,601評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評(píng)論 2 325
  • 正文 我和宋清朗相戀三年劲弦,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了耳标。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,161評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡邑跪,死狀恐怖次坡,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情画畅,我是刑警寧澤砸琅,帶...
    沈念sama閱讀 33,792評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站轴踱,受9級(jí)特大地震影響症脂,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜淫僻,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評(píng)論 3 307
  • 文/蒙蒙 一诱篷、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧嘁傀,春花似錦兴蒸、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至笑撞,卻和暖如春岛啸,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背茴肥。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評(píng)論 1 261
  • 我被黑心中介騙來泰國(guó)打工坚踩, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人瓤狐。 一個(gè)月前我還...
    沈念sama閱讀 45,618評(píng)論 2 355
  • 正文 我出身青樓瞬铸,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親础锐。 傳聞我的和親對(duì)象是個(gè)殘疾皇子嗓节,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評(píng)論 2 344

推薦閱讀更多精彩內(nèi)容

  • 上周自己負(fù)責(zé)的一個(gè)應(yīng)用出現(xiàn)頻繁full gc的問題,不得不嘗試優(yōu)化一下皆警。第一次做這種事只能先看看網(wǎng)上的文章拦宣,然后親...
    Acamy丶閱讀 6,745評(píng)論 0 8
  • 被文同時(shí)發(fā)布在CSDN上,歡迎查看。 APP內(nèi)存的使用鸵隧,是評(píng)價(jià)一款應(yīng)用性能高低的一個(gè)重要指標(biāo)绸罗。雖然現(xiàn)在智能手機(jī)的內(nèi)...
    大圣代閱讀 4,803評(píng)論 2 54
  • 內(nèi)存管理的目的就是讓我們?cè)陂_發(fā)中怎么有效的避免我們的應(yīng)用出現(xiàn)內(nèi)存泄漏的問題。內(nèi)存泄漏大家都不陌生了豆瘫,簡(jiǎn)單粗俗的講珊蟀,...
    宇宙只有巴掌大閱讀 2,360評(píng)論 0 12
  • Java 應(yīng)用性能優(yōu)化是一個(gè)老生常談的話題,典型的性能問題如頁(yè)面響應(yīng)慢靡羡、接口超時(shí)系洛,服務(wù)器負(fù)載高、并發(fā)數(shù)低略步,數(shù)據(jù)庫(kù)頻...
    Rick617閱讀 7,321評(píng)論 1 9
  • 好喜歡這個(gè)APP啊描扯,就像寫日記一樣,反正也不會(huì)有人看到趟薄。 不知道從什么時(shí)候開始不喜歡在朋友圈發(fā)東西了绽诚,很多情緒也沒...
    柚子晶閱讀 119評(píng)論 0 0