成都有哪些做網(wǎng)站的優(yōu)化一個(gè)網(wǎng)站需要多少錢
java線上問題排查之內(nèi)存分析
- 使用top命令
top命令顯示的結(jié)果列表中,會(huì)看到%MEM
這一列,這里可以看到你的進(jìn)程可能對(duì)內(nèi)存的使用率特別高。以查看正在運(yùn)行的進(jìn)程和系統(tǒng)負(fù)載信息,包括cpu負(fù)載、內(nèi)存使用、各個(gè)進(jìn)程所占系統(tǒng)資源等。
2.用jstat命令
jstat -gcutil 30 1000 10
命令,就是用jstat工具,對(duì)指定java進(jìn)程(30就是進(jìn)程id,通過ps -aux | grep java
命令就能找到),按照指定間隔,看一下統(tǒng)計(jì)信息,這里會(huì)每隔一段時(shí)間顯示一下,包括新生代的兩個(gè)S0、s1區(qū)、Eden區(qū),以及老年代的內(nèi)存使用率,還有young gc以及full gc的次數(shù)。
使用jstat -gcutil 30 500 5
表示每500毫秒打印一次Java堆狀況(各個(gè)區(qū)的容量、使用容量、gc時(shí)間等信息),打印5次
S0 S1 E O M CCS YGC YGCT FGC FGCT GCT
0.00 0.00 100.00 99.94 90.56 87.86 875 9.307 3223 5313.139 5322.446S0:幸存1區(qū)當(dāng)前使用比例
S1:幸存2區(qū)當(dāng)前使用比例
E:Eden Space(伊甸園)區(qū)使用比例
O:Old Gen(老年代)使用比例
M:元數(shù)據(jù)區(qū)使用比例
CCS:壓縮使用比例
YGC:年輕代垃圾回收次數(shù)
YGCT:年輕代垃圾回收消耗時(shí)間
FGC:老年代垃圾回收次數(shù)
FGCT:老年代垃圾回收消耗時(shí)間
GCT:垃圾回收消耗總時(shí)間
看到的東西類似下面那樣:
S0 S1 E O YGC FGC
26.80 0.00 10.50 89.90 86 954
老年代Full GC回收次數(shù)大于年輕代GC次數(shù),就肯定是有問題的。
所以jstat先看一下基本情況,馬上就能看出來(lái),其實(shí)就是大量對(duì)象沒法回收,一直在內(nèi)存里占據(jù)著,然后就差不多內(nèi)存快爆了。
- 使用jmap命令查看
執(zhí)行jmap -histo pid
可以打印出當(dāng)前堆中所有每個(gè)類的實(shí)例數(shù)量和內(nèi)存占用,如下,class name是每個(gè)類的類名([B是byte類型,[C是char類型,[I是int類型),bytes是這個(gè)類的所有示例占用內(nèi)存大小,instances是這個(gè)類的實(shí)例數(shù)量。
jmap -histo 1 | head -20 #查看占用內(nèi)存最大的前20個(gè)對(duì)象
- 把當(dāng)前堆內(nèi)存的快照轉(zhuǎn)儲(chǔ)到dumpfile_jmap.hprof文件中,然后可以對(duì)內(nèi)存快照進(jìn)行分析
使用jmap -dump:format=b,file=文件名 [pid]
,就可以把指定java進(jìn)程的堆內(nèi)存快照搞到一個(gè)指定的文件里去,但是jmap -dump:format
其實(shí)一般會(huì)比較慢一些,也可以用gcore 或者是 arthas工具來(lái)導(dǎo)出內(nèi)存快照
示例:
jmap -dump:format=b,file=D:/log/jvm/dumpfile_jmap.hprof 30
接著就是可以用MAT工具,或者是Eclipse MAT的內(nèi)存分析插件,來(lái)對(duì)hprof文件進(jìn)行分析。
注意:使用jdk自帶的jvisualvm分析,效果不理想,建議使用MAT 或者是 Jprofiler。這里我們使用MAT分析
- 總結(jié):
- 一般常見的OOM,要么是短時(shí)間內(nèi)涌入大量的對(duì)象,導(dǎo)致你的系統(tǒng)根本支持不住,此時(shí)你可以考慮優(yōu)化代碼,或者是加機(jī)器;要么是長(zhǎng)時(shí)間來(lái)看,你的很多對(duì)象不用了但是還被引用,就是內(nèi)存泄露了,你也是優(yōu)化代碼就好了;這就會(huì)導(dǎo)致大量的對(duì)象不斷進(jìn)入老年代,然后頻繁full gc之后始終沒法回收,就撐爆了
- 要么是加載的類過多,導(dǎo)致class在永久代理保存的過多,始終無(wú)法釋放,就會(huì)撐爆
- 線上jvm必須配置
-XX:+HeapDumpOnOutOfMemoryError,-XX:HeapDumpPath=/path/heap/dump
。因?yàn)檫@樣就是說OOM的時(shí)候自動(dòng)導(dǎo)出一份內(nèi)存快照,你就可以分析發(fā)生OOM時(shí)的內(nèi)存快照了,到底是哪里出現(xiàn)的問題。
如果有人問你有沒有處理過線上的問題,你就說有,最簡(jiǎn)單的,你說有個(gè)小伙子用了本地緩存,就放map里,結(jié)果沒控制map大小,可以無(wú)限擴(kuò)容,最終導(dǎo)致內(nèi)存爆了,后來(lái)解決方案就是用了一個(gè)ehcache框架,自動(dòng)LRU清理掉舊數(shù)據(jù),控制內(nèi)存占用就好了。