記錄一次OOM分析過程


工具:

  • jstat
  • jmap
  • jhat

1.jstat查看gc情況

S0C、S1C、S0U、S1U:Survivor 0/1區容量(Capacity)和使用量(Used)
EC、EU:Eden區容量和使用量
OC、OU:年老代容量和使用量
PC、PU:永久代容量和使用量
YGC、YGT:年輕代GC次數和GC耗時
FGC、FGCT:Full GC次數和Full GC耗時
GCT:GC總耗時

  

這次遇到的情況是,old區到了指定的回收閥值觸發fgc,但old區回收不了,持續增長(但一直頻繁fgc)

jvm配置如下:

-server -XX:PermSize=64m -XX:MaxPermSize=128m -Xmn500m -Xms3000m -Xmx3000m -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=60 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/home/apps/oom/gc.hprof  -XX:ErrorFile=/var/log/java_error_%p.log

 

2.當發現old區回收不了的時候,使用jmap分析內存情況。

jmap -heap pid

使用jmap -heap pid查看進程堆內存使用情況,包括使用的GC算法、堆配置參數和各代中堆內存使用情況。

例如:

Attaching to process ID 10253, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 24.65-b04

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

Heap Configuration:
   MinHeapFreeRatio = 40
   MaxHeapFreeRatio = 70
   MaxHeapSize      = 3145728000 (3000.0MB)
   NewSize          = 524288000 (500.0MB)
   MaxNewSize       = 524288000 (500.0MB)
   OldSize          = 5439488 (5.1875MB)
   NewRatio         = 2
   SurvivorRatio    = 8
   PermSize         = 67108864 (64.0MB)
   MaxPermSize      = 134217728 (128.0MB)
   G1HeapRegionSize = 0 (0.0MB)

Heap Usage:
New Generation (Eden + 1 Survivor Space):
   capacity = 471859200 (450.0MB)
   used     = 113244456 (107.99832916259766MB)
   free     = 358614744 (342.00167083740234MB)
   23.99962870279948% used
Eden Space:
   capacity = 419430400 (400.0MB)
   used     = 66465208 (63.38616180419922MB)
   free     = 352965192 (336.6138381958008MB)
   15.846540451049805% used
From Space:
   capacity = 52428800 (50.0MB)
   used     = 46779248 (44.61216735839844MB)
   free     = 5649552 (5.3878326416015625MB)
   89.22433471679688% used
To Space:
   capacity = 52428800 (50.0MB)
   used     = 0 (0.0MB)
   free     = 52428800 (50.0MB)
   0.0% used
concurrent mark-sweep generation:
   capacity = 2621440000 (2500.0MB)
   used     = 259229192 (247.22022247314453MB)
   free     = 2362210808 (2252.7797775268555MB)
   9.888808898925781% used
Perm Generation:
   capacity = 67108864 (64.0MB)
   used     = 37059440 (35.34263610839844MB)
   free     = 30049424 (28.657363891601562MB)
   55.22286891937256% used

19254 interned Strings occupying 2351584 bytes.

jmap -heap 只能查看jvm各個區的詳細使用情況,內存中到底有哪些數據(咬着old區不放)得用jmap -histo進行分析。

jmap -histo[:live] pid

例如:

num     #instances         #bytes  class name
----------------------------------------------
   1:         32727       88492856  [I
   2:        369677       62058808  [C
   3:        145200       54408968  [B
   4:        545638       17460416  java.util.HashMap$Entry
   5:        451316       14442112  org.wltea.analyzer.dic.DictSegment
   6:        158024       10051408  [Ljava.lang.Object;
   7:         59193        8940656  <constMethodKlass>
   8:         59193        7588736  <methodKlass>
   9:          6105        7139824  <constantPoolKlass>
  10:         39329        6230272  [Ljava.util.HashMap$Entry;
  11:        255466        6131184  java.lang.String
  12:        182746        5847872  [Lorg.wltea.analyzer.dic.DictSegment;
  13:          6097        4220448  <instanceKlassKlass>
  14:          5064        3900032  <constantPoolCacheKlass>
  15:        100084        3202688  org.apache.lucene.document.LazyDocument$LazyField
  16:         78719        3148760  java.util.LinkedHashMap$Entry
  17:         11980        3120656  [S
  18:        122352        2936448  java.util.ArrayList
  19:          9747        2740192  [J
  20:         95649        2295576  java.util.LinkedList$Node
  21:         53484        2139360  org.apache.lucene.document.FieldType
  22:        125687        2010992  java.lang.Character
  23:         41021        1969008  org.apache.lucene.analysis.tokenattributes.PackedTokenAttributeImpl
  24:         53663        1913576  [Lorg.apache.lucene.util.automaton.Transition;

 class name是對象類型,說明如下:

B  byte
C  char
D  double
F  float
I  int
J  long
Z  boolean
[  數組,如[I表示int[]
[L+類名 其他對象

如果還需要看更加詳細的信息,則使用:

jmap -dump:format=b,file=dumpFileName pid

 

dump出來的文件可以用MAT、VisualVM等工具查看,也可以使用jhat。

jhat -port 9999 dumpFileName

如果dump出來的文件過大,可能需要指定Xmx(jhat實際啟動了一個web應用)。

jhat -J-Xmx1000m -port 9999 dumpFileName

啟動成功后,則可以通過瀏覽器查看:

ip:port

例如:

 

 

在該頁面的最后面有一些查詢工具,例如:OQL(object query language)

 

例如上圖查詢的是長度大於256的int數組。

 

------------------------------------

企業開發的時候,有可能碰到的問題:

  • oom
  • 內存泄露
  • 線程死鎖
  • 鎖爭用
  • java進程消耗cpu過高 

工具:

  • jps(java virtual machine process status tool)

jps主要用來輸出JVM中運行的進程狀態信息。語法格式如下:

jps [options] [hostid]

q 不輸出類名、Jar名和傳入main方法的參數
-m 輸出傳入main方法的參數
-l 輸出main類或Jar的全限名
-v 輸出傳入JVM的參數

 

  • jstack

 jstack主要用來查看某個Java進程內的線程堆棧信息。

檢查過程:

1)得到相應的進程號(ps -ef |grep ***)

2)查詢該進程對應的線程信息(top -Hp pid)

這里的Pid需要轉成16進制,后面需要用到。

[apps@java1818 bin]$ printf "%x\n" 10831
2a4f

使用jstack進行分析

[apps@java1818 bin]$ jstack 10253 | grep 2a4f
"http-bio-2223-exec-172" daemon prio=10 tid=0x00007fb2d400a000 nid=0x2a4f waiting on condition [0x00007fb28c5c4000]

也可以將信息dump到文件中進行分析,更加方便。  

  

  • jmap ( memory map ) / jhat ( java heap analysis tool )

 jmap用來查看堆內存使用狀況,一般結合jhat使用。

jmap -heap pid
jmap -histo[:live] pid
jmap -dump:format=b,file=dumpFileName pid

  

  • jstat

堆內存 = 年輕代 + 年老代 + 永久代
年輕代 = Eden區 + 兩個Survivor區(From和To)

  

  • hprof ( heap/cpu profiling tool )

 hprof能夠展現CPU使用率,統計堆內存使用情況。

 

參考資料:

http://my.oschina.net/feichexia/blog/196575

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM