天天看點

jvm垃圾記憶體回收問題

CrashReport系統在遊戲内測當天出現了異常情況JVM僵死,通過top -p <PID> -H 結合jstack(jstack -m -l pid)檢視,發現是VM Thread線程CPU占用100%,線程ID好為18540,線程資訊如下:

----------------- 18540 -----------------

0xb7904280      _ZN9MarkSweep12follow_stackEv + 0x30

0xb79b0637      _ZN11PSMarkSweep17mark_sweep_phase1Eb + 0xe7

0xb79af737      _ZN11PSMarkSweep16invoke_no_policyEb + 0x3c7

0xb79ba0ae      _ZN10PSScavenge6invokeEv + 0x12e

0xb797f999      _ZN20ParallelScavengeHeap19failed_mem_allocateEjb + 0x49

0xb7ab191a      _ZN29VM_ParallelGCFailedAllocation4doitEv + 0x5a

0xb7ac0096      _ZN12VM_Operation8evaluateEv + 0x46

0xb7abf523      _ZN8VMThread18evaluate_operationEP12VM_Operation + 0x83

0xb7abf794      _ZN8VMThread4loopEv + 0x194

0xb7abf280      _ZN8VMThread3runEv + 0x80

0xb796d64e      _Z10java_startP6Thread + 0x14e

0x0056849b      start_thread + 0xcb

Parallel GC 是JVM的垃圾回收線程( ParallelGC垃圾回收方式的特點是在New區開啟多線程回收)

既然是垃圾回收線程CPU占用100%,那麼說明我們的應用的JVM記憶體使用有問題,借助jstat檢視JVM的記憶體資訊如下:

jstat -gcutil pid 5000 #這裡是說每隔5000毫秒列印異常JVM記憶體資訊

存活區0

存活區1

伊甸區

Old區

永久區

新生帶GC次數

新生帶GC時間

Full GC次數

Full GC時間

GC的總時間

 S0

S1

E

O

P

YGC

YGCT

FGC

FGCT

GCT

 0.00

100

98.75

584

13.28

1447

3699.659

3712.939

1448

3702.135

3715.416

存活區0和存活區1的記憶體占用都是0%,伊甸區使用100%,Old區使用也是100%,Full GC的次數達到1448(3個小時内,差不多9s做一次Full GC,每次Full GC花費2.56s)

也就是說我們的應用頻繁的在做Full GC,而且Full GC消耗的時間也比較長,應用在做Full GC是整個應用是會阻塞的,是以在這種情況下我們的應用幾乎是不可用的。

什麼情況下會引發Full GC呢?參考下圖:

Old區記憶體不夠是JVM會觸發Full GC,由于Old區一直是滿的,是以會頻繁觸發Full GC,但是這個頻度也不高,應該不至于導緻CPU使用100%,我們用的是Parallel GC(并行GC),并行GC是說在新生帶會采取多線程來進行垃圾回收,由于我們Eden區也是滿的,是以GC的線程會CPU占用100%。

怎麼檢視我們的JVM每個區的記憶體大小情況呢?用jstat -gccapacity <PID>可以得到結果如下:

新生帶最小

新生帶最大

新生帶目前

存活區

老年帶最小

老年帶最大

老年帶目前

Old區記憶體占用

永久區最小

永久區最大

永久區目前

永久區記憶體占用

Full GC 次數

NGCMN

NGCMX

NGC

S0C

S1C

EC

OGCMN

OGCMX

OGC

OC

PGCMN

PGCMX

PGC

PC

21824

349504

64384

2112

3904

56448

43712

699072

178496

16384

65536

35712

146

9

21.3125

341.3125

62.875

2.0625

3.8125

55.125

42.6875

682.6875

174.3125

16

64

34.875

我們的Eden區較小,這個可能會觸發JVM的一個BUG(1.6u18前的版本,我們的版本是:java version "1.6.0_37")正好在這個範圍内,具體資訊檢視:http://www.oschina.net/question/1092_24066

嘗試更新jdk版本或者調整JVM記憶體參數解決該問題。

繼續閱讀