【JVM】線上應用故障排查


 

 

高CPU占用

一個應用占用CPU很高,除了確實是計算密集型應用之外,通常原因都是出現了死循環。

 

根據top命令,發現PID為28555的Java進程占用CPU高達200%,出現故障。

通過ps aux | grep PID命令,可以進一步確定是tomcat進程出現了問題。但是,怎么定位到具體線程或者代碼呢?

首先顯示線程列表:

ps -mp pid -o THREAD,tid,time

找到了耗時最高的線程28802,占用CPU時間快兩個小時了!

 

其次將需要的線程ID轉換為16進制格式:

printf "%x\n" tid

 

 

最后打印線程的堆棧信息:

jstack pid |grep tid -A 30

 

 找到出現問題的代碼了!

 

最后,總結下排查CPU故障的方法和技巧有哪些:

1、top命令:Linux命令。可以查看實時的CPU使用情況。也可以查看最近一段時間的CPU使用情況。

2、PS命令:Linux命令。強大的進程狀態監控命令。可以查看進程以及進程中線程的當前CPU使用情況。屬於當前狀態的采樣數據。

3、jstack:Java提供的命令。可以查看某個進程的當前線程棧運行情況。根據這個命令的輸出可以定位某個進程的所有線程的當前運行狀態、運行代碼,以及是否死鎖等等。

4、pstack:Linux命令。可以查看某個進程的當前線程棧運行情況。

 

 

高內存占用

搞Java開發的,經常會碰到下面兩種異常:

1、java.lang.OutOfMemoryError: PermGen space

2、java.lang.OutOfMemoryError: Java heap space

要詳細解釋這兩種異常,需要簡單重提下Java內存模型。

 

Java內存模型是描述Java程序中各變量(實例域、靜態域和數組元素)之間的關系,以及在實際計算機系統中將變量存儲到內存和從內存取出變量這樣的低層細節。

在Java虛擬機中,內存分為三個代:新生代(New)、老生代(Old)、永久代(Perm)。

(1)新生代New:新建的對象都存放這里

(2)老生代Old:存放從新生代New中遷移過來的生命周期較久的對象。新生代New和老生代Old共同組成了堆內存。

(3)永久代Perm:是非堆內存的組成部分。主要存放加載的Class類級對象如class本身,method,field等等。

如果出現java.lang.OutOfMemoryError: Java heap space異常,說明Java虛擬機的堆內存不夠。原因有二:

(1)Java虛擬機的堆內存設置不夠,可以通過參數-Xms、-Xmx來調整。

(2)代碼中創建了大量大對象,並且長時間不能被垃圾收集器收集(存在被引用)。

如果出現java.lang.OutOfMemoryError: PermGen space,說明是Java虛擬機對永久代Perm內存設置不夠。

一般出現這種情況,都是程序啟動需要加載大量的第三方jar包。例如:在一個Tomcat下部署了太多的應用。

 

從代碼的角度,軟件開發人員主要關注java.lang.OutOfMemoryError: Java heap space異常,減少不必要的對象創建,同時避免內存泄漏。

現在以一個實際的例子分析內存占用的故障排查。

2G19({7(0}N(FIL09LH175N

通過top命令,發現PID為9004的Java進程一直占用比較高的內存不釋放(24.7%),出現高內存占用的故障。

想起上一篇線上應用故障排查之一:高CPU占用介紹的PS命令,能否找到具體是哪個的線程呢?

ps -mp 9004 -o THREAD,tid,time,rss,size,%mem

1

遺憾的是,發現PS命令可以查到具體進程的CPU占用情況,但是不能查到一個進程下具體線程的內存占用情況。

 

只好尋求其他方法了,幸好Java提供了一個很好的內存監控工具:jmap命令

jmap命令有下面幾種常用的用法:

•jmap [pid]

•jmap -histo:live [pid] >a.log

•jmap -dump:live,format=b,file=xxx.xxx [pid]

用得最多是后面兩個。其中,jmap -histo:live [pid] 可以查看當前Java進程創建的活躍對象數目和占用內存大小。

jmap -dump:live,format=b,file=xxx.xxx [pid] 則可以將當前Java進程的內存占用情況導出來,方便用專門的內存分析工具(例如:MAT)來分析。

這個命令對於分析是否有內存泄漏很有幫助。具體怎么使用可以查看本博的另一篇文章:利用Eclipse Memory Analyzer Tool(MAT)分析內存泄漏

 

這里詳細介紹下jmap -histo:live [pid] 命令:

1

從上圖可以看出,int數組、constMethodKlass、methodKlass、constantPoolKlass都占用了大量的內存。

特別是占用了大量內存的int數組,需要仔細檢查相關代碼。

 

最后,總結下排查內存故障的方法和技巧有哪些:

1、top命令:Linux命令。可以查看實時的內存使用情況。  

2、jmap -histo:live [pid],然后分析具體的對象數目和占用內存大小,從而定位代碼。

3、jmap -dump:live,format=b,file=xxx.xxx [pid],然后利用MAT工具分析是否存在內存泄漏等等。


免責聲明!

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



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