JVM監控-內存泄露與高CPU占用排查(九)


說明

一般我們發現內存持續增長,但是並沒有得到釋放,我們就需要排查是否內存泄露

代碼模擬

通過ThreadLocal模擬內存泄露  

為什么ThreadLocal會內存泄露?參考:《ThreadLocal》

@RequestMapping("/testController")
@Controller
public class TestController {

    @RequestMapping(value = "/test3")
    @ResponseBody
    public String test3() {
        ThreadLocal localVariable = new ThreadLocal();
        localVariable.set(new Byte[4096 * 1024]);// 為線程添加變量
        return "success";
    }
}

AB壓測模擬

ab使用例子:《壓測工具-ab》

ab -c 500 -n 1000 localhost:8999/testController/test3

分析

1.當我們發現機器內存持續升高 我們可以使用top命令來定位java程序

  

2.我們可以通過top -Hp 查看各個線程cpu 和 內存占用情況

 

紅框框起來的內存是我有個疑惑,應該是各個線程占用的內存,但是這里好像顯示的是總內存;可能是因為堆內存是線程共享 所以這里顯示的是總的堆占用內存。

3.我們可以通過jstack dump到線程堆棧,對於分析線程死鎖 cpu占用過高代碼定位很有幫助

這里我們以21141為例,先將21141轉換為16進制:在線轉換 得到5295 通過jstack dump線程堆棧信息 

或者通過命令 printf  '%x/n' tid 把線程id轉化為十六進制

jstack 19751|grep -A20 5295 //查找5295 並打印后20行 19751為PID 5295 為線程id 16進制
jstack 19751|grep -A20 5295  >/root/threaddump.txt//查找5295 並打印后20行 並輸出到指定文件 
jstack 19751  >/root/threaddump.txt// dump整個線程堆棧並輸出到指定文件

可以發現該線程一直處於 TIMED_WAITING 狀態  此時 CPU 使用率和負載並沒有出現異常,我們可以排除死鎖或 I/O 阻塞的異常問題了。

 

4.通過jmap或者jstack查看堆內存使用情況

參數詳解請看:《jvm-內存監控工具》

可以發現,老年代的使用率幾乎快占滿了,而且內存一直得不到釋放

 ./jmap -heap  19751
 ./jstack -gc 19751

 

 5.查看gc信息

參數詳解請看:《jvm-內存監控工具》

jstat -gcutil pid  1000//1秒一次采集gc信息

 6.我們可以通過jmap查看內存存活對象情況

可以發現[Ljava.lang.Byte; 有161個實例 占用了大量空間

jmap -histo  pid   所有對象創建數量
jmap -histo:live pid 只查看存活對象
jmap -histo  pid  >/root/object.txt 所有對象創建數量並保存到指定文件
jmap -histo:live pid /root/object.txt 只查看存活對象並保存到指定文件

 

 

7.dump內存信息進行分析參考:《JVM學習-內存監控工具(五)-dump內存信息》

jmap -dump:format=b,file=/Users/liqiang/Desktop/logs/heap.hprof  pid ///Users/liqiang/Desktop/logs/heap.hprof為輸出文件

分析dump *.hprof文件工具

visualVM

下載地址:https://visualvm.github.io/download.html

1導入dump文件

 

 這里可以分析線程和內存對象情況,我們切換到Object

 

 

我們可以看到Byte占用了90%以上的內存 我們可以查看引用對象

 

 

 

 

 看到引用對象是ThreadLocal 所以判定是使用ThreadLocal 使用完畢並沒有釋放導致內存泄露

MAT

下載地址需要FQ 暫時不測試了

 

異常情況解決方式

1.Unable to open socket file: target process not responding or HotSpot VM not loaded The -F option can be used when the target process is not responding

切換到程序所在的用戶

2.注:如果使用jmap和jstack報錯 可能是多jdk導致切換當前使用jdk 在bin下面通過./指定調用:參考《linux查看jdk安裝路徑》

 


免責聲明!

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



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