現(xiàn)象
java服務(wù)嫩实,運(yùn)行1-2天閃退。閃退問(wèn)題通常比較難查搏恤,因?yàn)槿罩静蝗ナ伲杂涗浺幌卤敬螁?wèn)題原因定位。
定位問(wèn)題過(guò)程
1 先看應(yīng)用日志
一般閃退都不會(huì)記錄(應(yīng)用來(lái)不及寫(xiě))熟空,但是可以碰碰運(yùn)氣看看最后在執(zhí)行什么藤巢。
2 本地排查java內(nèi)存泄漏
- 安裝Jprofile
- 選擇IDEA-->Perferences-->Plugins打開(kāi)安裝JProfile插件的界面
- 下載最新JProfile壓縮包
- 本地運(yùn)行java程序
-
在Jprofiler選擇你要profile的進(jìn)程
image.png -
選擇live memory--> mark current --> 執(zhí)行疑似內(nèi)存泄漏的操作-->點(diǎn)擊GC
如果有對(duì)象不能被GC,則疑似發(fā)生了內(nèi)存泄漏
image.png -
進(jìn)一步分析泄漏的原因息罗,右鍵選中掂咒,查看heap
選擇不進(jìn)行GC查看前面新增的對(duì)象(勾選了GC選項(xiàng)后會(huì)再進(jìn)行一次GC,前面GC過(guò)了就不用了迈喉。)
** 補(bǔ)充:內(nèi)存泄漏一般看堆绍刮,棧一般存運(yùn)行時(shí)數(shù)據(jù) **
image.png -
查看引用(references),show path to gc root挨摸,能看到對(duì)象的引用路徑
image.png - 這里可以先合并統(tǒng)計(jì)孩革,找到最多的對(duì)象再挨個(gè)定位,要一個(gè)個(gè)查得运,找到問(wèn)題所在膝蜈。
問(wèn)題到這里查到了一些微小的內(nèi)存泄漏,但是感覺(jué)不至于服務(wù)1-2天閃退熔掺。查到了某寫(xiě)操作占用大量?jī)?nèi)存饱搏,但是可以被GC回收。需要進(jìn)一步定位置逻。
3 服務(wù)器查看系統(tǒng)日志
系統(tǒng)日志一般存放在/var/log中
-
不同的系統(tǒng)日志有不同的含義
- /var/log/cron 工作調(diào)度
- /var/log/dmesg 內(nèi)核檢測(cè)過(guò)程中產(chǎn)生的信息
- /var/log/lastlog 檢測(cè)所有賬號(hào)登陸信息
- /var/log/maillog或/var/log/mail/* 郵件
- /var/log/messages 記錄系統(tǒng)發(fā)生的所有錯(cuò)誤信息
- /var/log/secure 涉及賬號(hào)密碼信息
- /var/log/wtmp,/var/log/faillog 記錄正確登陸系統(tǒng)與錯(cuò)誤登陸系統(tǒng)者的賬號(hào)信息
- /var/log/httpd/,/var/log/news/,/var/log/samba/* 不同網(wǎng)絡(luò)服務(wù)的信息記錄處
- /var/log/syslog (本人用的騰訊云的系統(tǒng)日志)**
先從應(yīng)用日志中定位到閃退的時(shí)間(從某個(gè)時(shí)間點(diǎn)開(kāi)始沒(méi)有日志了)
然后搜索一下 /var/log/syslog
-
在閃退時(shí)間附近看下是否有異常推沸,發(fā)現(xiàn)有oom-killer
image.png Out of memory killer
在可用內(nèi)存極低的情況下會(huì)殺死某些進(jìn)程。只要達(dá)到觸發(fā)條件就會(huì)激活, 選中某個(gè)進(jìn)程并殺掉。 通常采用啟發(fā)式算法, 對(duì)所有進(jìn)程計(jì)算評(píng)分(heuristics scoring), 得分最低的進(jìn)程將被 kill 掉鬓催。它既不由JVM觸發(fā),也不由JVM代理, 而是系統(tǒng)內(nèi)核內(nèi)置的一種安全保護(hù)措施肺素。然后結(jié)合第二步,發(fā)現(xiàn)有一些操作會(huì)讓內(nèi)存暴漲(緩存了較多數(shù)據(jù)來(lái)追求性能優(yōu)化)深浮,雖然可以被GC压怠,但是導(dǎo)致服務(wù)器內(nèi)存過(guò)低。解決方式就是內(nèi)存擴(kuò)容一下飞苇,或者優(yōu)化應(yīng)用使用的內(nèi)存。
4 查問(wèn)題過(guò)程中蜗顽,其他輔助分析的工具
- 先從free命令理解下linux內(nèi)存布卡。free -h
total
總內(nèi)存=used
已使用+free
空閑。buffers
:用來(lái)存儲(chǔ)目錄里面有什么內(nèi)容雇盖。 比如執(zhí)行了ls /etc之后 buffers增長(zhǎng)了146980忿等。cached
:用來(lái)記憶我們打開(kāi)的文件。 比如新建一個(gè)文件 cached增長(zhǎng)了258804崔挖。swap
:應(yīng)用所需內(nèi)存超過(guò)物理內(nèi)存時(shí)贸街,就會(huì)發(fā)生頁(yè)面切換,通常要為系統(tǒng)配置swap空間狸相。 他在一個(gè)獨(dú)立磁盤(pán)分區(qū)上薛匪,物理內(nèi)存耗盡后,會(huì)將應(yīng)用最少運(yùn)行的部分置換到swap空間里(活躍的不置換)脓鹃,如果要訪問(wèn)swap空間的部分逸尖,就必須將他置換進(jìn)內(nèi)存,對(duì)應(yīng)用造成響應(yīng)和吞吐量影響瘸右。 JVM垃圾回收在頁(yè)面交換時(shí)性能很差娇跟,為了回收不可達(dá)對(duì)象所占用空間,需要訪問(wèn)大量?jī)?nèi)存太颤,如果堆的一部分被置換出去了苞俘,就必須先置換進(jìn)內(nèi)存以便垃圾回收器掃描存活對(duì)象,增加垃圾收集的持續(xù)的時(shí)間龄章,并且又stop the world吃谣,引起長(zhǎng)時(shí)間停頓。-buffers/cache
的意思: 等于used-buffers-cached瓦堵。 從OS系統(tǒng)的角度來(lái)看,buffers/cached 都是屬于系統(tǒng)使用的基协,應(yīng)用使用的要減掉他們,反應(yīng)的是被程序?qū)崒?shí)在在吃掉的內(nèi)存菇用。+buffers/cache
的意思: 等于free + buffers + cached 從應(yīng)用的角度來(lái)看澜驮,buffer/cached只是系統(tǒng)為了提高文件讀取的性能而設(shè)置的,當(dāng)自己應(yīng)用需要用到這塊的空間時(shí)惋鸥,系統(tǒng)可以把它們回收掉杂穷,給應(yīng)用程序使用悍缠,所以他們是應(yīng)用可以使用的內(nèi)存總數(shù)。shared
: 據(jù)說(shuō)是進(jìn)程間共享內(nèi)存耐量,了解不多飞蚓,因?yàn)檫@個(gè)參數(shù)出現(xiàn)的問(wèn)題沒(méi)有過(guò)。
-
下面用工具vmstat查問(wèn)題廊蜒,通常從下面兩個(gè)方面看
image.png
- 內(nèi)存不夠用
swpd
:使用的虛擬內(nèi)存大小趴拧。free
:空閑的物理內(nèi)存大小。buff
:用作緩沖的內(nèi)存大小山叮。cache
:用作緩存的內(nèi)存大小著榴。si
:每秒從交換區(qū)寫(xiě)到內(nèi)存的大小,由磁盤(pán)調(diào)入內(nèi)存屁倔。so
:每秒寫(xiě)入交換區(qū)的內(nèi)存大小脑又,由內(nèi)存調(diào)入磁盤(pán)。
如果swpd锐借,so,si比較高问麸,說(shuō)明內(nèi)存資源不足,已經(jīng)占用交換區(qū)資源钞翔。需要增加內(nèi)存严卖。