JVM OOM 排查

1、jdk 自帶基礎(chǔ)工具

2、MAT 分析dump

3、VM 實時監(jiān)控

4 、遇到過OOM

內(nèi)存溢出有哪些

1、Java堆溢出 (java.lang.OutofMemoryError:Java heap space)

2、PermGen space

3、StackOverflowError(虛擬機在擴展棧時無法申請到足夠的內(nèi)存空間)

4、直接崩潰

內(nèi)存溢出與泄漏

內(nèi)存溢出 out of memory:

是指程序在申請內(nèi)存時,沒有足夠的內(nèi)存空間供其使用,出現(xiàn)out of memory;

內(nèi)存泄露 memory leak,

是指程序在申請內(nèi)存后,無法釋放已申請的內(nèi)存空間,一次內(nèi)存泄露危害可以忽略,但內(nèi)存泄露堆積后果很嚴重,無論多少內(nèi)存,遲早會被占光

一、jdk 自帶基礎(chǔ)工具


1、 ** jps(Java Virtual Machine Process Status Tool) **

實際中這是最常用的命令,下面要介紹的小工具更多的都是先要使用jps查看出當前有哪些Java進程,獲取該Java進程的id后再對該進程進行處理。

jps [options] [hostid]

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

[root@iZbp11b3erzreb4xi5utvzZ /]# jps -ml

22611 /usr/lib/jenkins/jenkins.war --logfile=/var/log/jenkins/jenkins.log --webroot=/var/cache/jenkins/war 740 org.apache.catalina.startup.Bootstrap start19942 org.apache.zookeeper.server.quorum.QuorumPeerMain /mnt/zk/zookeeper-3.4.13/bin/../conf/zoo.cfg20537 sun.tools.jps.Jps -ml11309 org.sonatype.nexus.bootstrap.jsw.JswLauncher ./conf/jetty.xml ./conf/jetty-requestlog.xml32190 org.apache.catalina.startup.Bootstrap start

2、 jstack

jstack 主要用來查看某個Java進程內(nèi)的線程堆棧信息。語法格式如下:

jstack [option] pid

jstack [option] executable core

jstack [option] [server-id@]remote-hostname-or-ip

pid: java應(yīng)用程序的進程號,一般可以通過jps來獲得;

executable:產(chǎn)生core dump的java可執(zhí)行程序($JAVA_HOME/bin/java);

core:打印出的core文件;(jvm崩潰產(chǎn)生的core文件,從hs_err_pid log file 查看)

emote-hostname-or-ip:遠程debug服務(wù)器的名稱或IP

server-id: 唯一id,假如一臺主機上多個遠程debug服務(wù);

option 說明如下:

-l,會打印出額外的鎖信息,在發(fā)生死鎖時可以用jstack -l pid來觀察鎖持有情況

-m 不僅會輸出Java堆棧信息,還會輸出C/C++堆棧信息(比如Native方法)

jstack -l pid

image

RUNNABLE,在虛擬機內(nèi)執(zhí)行的。運行中狀態(tài),可能里面還能看到locked字樣,表明它獲得了某把鎖。

BLOCKED,受阻塞并等待監(jiān)視器鎖。被某個鎖(synchronizers)給block住了。

WATING,無限期等待另一個線程執(zhí)行特定操作。等待某個condition或monitor發(fā)生,一般停留在park(), wait(), sleep(),join() 等語句里。

TIMED_WATING,有時限的等待另一個線程的特定操作。和WAITING的區(qū)別是wait() 等語句加上了時間限制 wait(timeout)。

TERMINATED,已退出的。

查看耗時線程

top -Hp pid

image

printf "%x\n" 21226

獲取耗時線程id 的十六進制

52ec

獲取耗時信息

[root@2 logs]# jstack 21222 | grep 52ec

"GC task thread#3 (ParallelGC)" os_prio=0 tid=0x00007fee24027000 nid=0x52ec runnable

3、jmap(Memory Map)

jmap導(dǎo)出堆內(nèi)存,然后使用jhat來進行分析

jmap [option] pid
jmap [option] executable core
jmap [option] [server-id@]remote-hostname-or-ip

參數(shù)如下:

-heap:打印jvm heap的情況
-histo:打印jvm heap的直方圖。其輸出信息包括類名,對象數(shù)量,對象占用大小。

-histo:live :同上,但是只打印存活對象的情況

-permstat:打印permanent generation heap情況(持久代)

輸出 類加載器名稱、對象是否存活、對象地址、父類加載器、已加載的類大小等信息

-dump:<dump-options> 打印 dump(內(nèi)存使用) 日志文件

jmap -heap pid

查看進程堆內(nèi)存使用情況:****包括使用的GC算法、堆配置參數(shù)和各代中堆內(nèi)存使用

[root@iZbp11b3erzreb4xi5utvzZ ~]# jmap -heap 32326

Attaching to process ID 32326, please wait...

Debugger attached successfully.

Server compiler detected.

JVM version is 25.161-b12

using thread-local object allocation.

Parallel GC with 4 thread(s)

Heap Configuration:

MinHeapFreeRatio = 0

MaxHeapFreeRatio = 100

MaxHeapSize = 536870912 (512.0MB)

NewSize = 201326592 (192.0MB)

MaxNewSize = 201326592 (192.0MB)

OldSize = 335544320 (320.0MB)

NewRatio = 2

SurvivorRatio = 8

MetaspaceSize = 21807104 (20.796875MB)

CompressedClassSpaceSize = 1073741824 (1024.0MB)

MaxMetaspaceSize = 17592186044415 MB

G1HeapRegionSize = 0 (0.0MB)

Heap Usage:

PS Young Generation

Eden Space:

capacity = 121634816 (116.0MB)

used = 105409240 (100.52608489990234MB)

free = 16225576 (15.473915100097656MB)

86.6604180171572% used

From Space:

capacity = 38797312 (37.0MB)

used = 6225208 (5.936820983886719MB)

free = 32572104 (31.06317901611328MB)

16.045462118612754% used

To Space:

capacity = 39845888 (38.0MB)

used = 0 (0.0MB)

free = 39845888 (38.0MB)

0.0% used

PS Old Generation

capacity = 335544320 (320.0MB)

used = 19401584 (18.502792358398438MB)

free = 316142736 (301.49720764160156MB)

5.782122611999512% used

19968 interned Strings occupying 2526840 bytes.

jmap -histo[:live] pid

查看堆內(nèi)存中的對象數(shù)目、大小統(tǒng)計直方圖,如果帶上live則只統(tǒng)計活對象

[root@iZbp11b3erzreb4xi5utvzZ ~]# jmap -histo 32326

num #instances #bytes class name


1: 351157 49044840 [C

2: 140145 26768472 [B

3: 30637 18927560 [I

4: 191987 4607688 java.lang.String

5: 46693 3523560 [Ljava.lang.Object;

6: 27813 2447544 java.lang.reflect.Method

7: 30591 2447048 [S

8: 58522 2340880 java.util.TreeMap$Entry

9: 81040 1683096 [Ljava.lang.Class;

10: 38542 1541680 java.util.HashMap$KeyIterator

11: 44546 1069104 java.lang.StringBuilder

12: 18696 1046976 java.util.concurrent.ConcurrentHashMap$KeyIterator

13: 37638 903312 java.util.CollectionsUnmodifiableCollection1

14: 10197 896216 [Ljava.util.HashMap$Node;

15: 7902 879416 java.lang.Class

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

B byte

C char

D double

F float

I int

J long

Z boolean

[ 數(shù)組,如[I表示int[]

[L+類名 其他對象

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

[root@iZbp11b3erzreb4xi5utvzZ ~]# jmap -dump:format=b,file=/mnt/d.bat 32326

Dumping heap to /mnt/d.bat ...

Heap dump file created

問題:

這些工具真靠譜嗎?

大應(yīng)用異常下 直接使用jmap jstack 根本無法加載內(nèi)存信息或者耗時很久?

有什么可以替代嗎?

gcore?


二、MAT 分析Dump

Dump 是什么

Dump是反應(yīng)Java堆使用情況的內(nèi)存鏡像,其中主要包括系統(tǒng)信息、虛擬機屬性、完整的線程Dump、所有類和對象的狀態(tài)等。 一般,在內(nèi)存不足、GC異常等情況下,我們就會懷疑有內(nèi)存泄漏。這個時候我們就可以制作堆Dump來查看具體情況。分析原因。

Dump 文件的分析有多種方式

1、命令jhat 分析(麻煩)

  2、**VisualVM** 工具分析 

  3、MAT 分析

MAT分析

J2SE中提供了一個簡單的命令行工具來對java程序的cpu和heap進行 profiling(剖析面),叫做HPROF

Shallow Size

對象自身占用的內(nèi)存大小,不包括它引用的對象。

針對非數(shù)組類型的對象,它的大小就是對象與它所有的成員變量大小的總和。當然這里面還會包括一些java語言特性的數(shù)據(jù)存儲單元。

針對數(shù)組類型的對象,它的大小是數(shù)組元素對象的大小總和。

Retained Size

Retained Size=當前對象大小+當前對象可直接或間接引用到的對象的大小總和。(間接引用的含義:A->B->C, C就是間接引用)

換句話說,Retained Size就是當前對象被GC后,從Heap上總共能釋放掉的內(nèi)存。

不過,釋放的時候還要排除被GC Roots直接或間接引用的對象。他們暫時不會被被當做Garbage。

**List objects --> with outgoing references **

:查看當前對象持有的外部對象引用(在對象關(guān)系圖中為從當前對象指向外的箭頭)

**List objects --> with incoming references **

:查看當前對象被哪些外部對象所引用(在對象關(guān)系圖中為指向當前對象的箭頭)

三、VM 實時監(jiān)控

四、遇到過OOM

1、剛開始用eclipse 開發(fā) ,沒事就本地OOM

2、DateForm oom

3、POI 導(dǎo)出xls 包含圖片

4、萬惡的死循環(huán)

5、hashmap

6、websocket 大內(nèi)存長久占用

事故:

1、遇到fullgc 了,oom了?完蛋

2、抓不出來dump ?完蛋

3、jmap、jstack 都用不了?完蛋

1、記錄時間點

2、抓住一切日志可用日志(應(yīng)用日志)

3、慢慢分析

參考

GC:https://www.cnblogs.com/wozixiaoyao/p/5658950.html

jstack:http://www.itdecent.cn/p/08b816d9b34f

executable core:https://lydawen.iteye.com/blog/2215300

內(nèi)存劃分:https://www.cnblogs.com/haitaofeiyang/p/8392268.html

mat:http://www.cnblogs.com/trust-freedom/p/6744948.html#histogram

oom:https://mp.weixin.qq.com/s/kJe8WScwB4XcqRNE2vM7EA?

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容