jmap+MAT实战内存溢出
一、堆區和非堆區
前言:
如果發生內存溢出,主要是通過內存映像文件,來查看到底是那些類,一直在占有沒有釋放。
- 1.1 情況分析:
第一種內存溢出:有可能內存泄漏
第二種內存溢出:也有可能內存分配不足導致的
假若:內存泄漏,我們要找到是那個地方把它泄露出去了,一直占有沒有釋放。
java中的內存泄漏:指new了一個對象之后,一直不釋放,這樣的內存
- 1.2 如何導出內存映像文件?
- 1.2.1 內存溢出JVM自動導出:
當發生內存溢出的時候讓jvm自動導出
設置參數:
#當發生內存溢出的時候,把HeapDump導出
#當發生內存溢出的時候,把HeapDump出來的路徑
-XX:HeapDumpPath=./- 1.2.2 使用jmap命令手動導出:
當發生內存溢出的時候,再去dump就有點晚了,當成程序運行一點時間后,我們用jmap手動導出內存映像文件,來具體分析:
執行命令:
格式:jmap -dump:format=b,file=heap.hprof pid
命令行輸出:
看到以上提示,說明導出成功!!!
二、MAT分析dump文件
打開dump文件
三、案例演示
框架springboot
在瀏覽器地址欄輸入:https://start.spring.io/
- 3.1 生成一個springboot項目
- 3.2 解壓壓縮包
- 3.3 在STS或eclipse或idea導入解壓的項目
- 3.4創建一個MemoryController和User對象
實現原理:
因為controller不被回收,它里面的成員變量也 是不會被被回收的,這樣就是導致list里面的對象越來越多,占得內存會越來越大,這樣就會把我們這個內存撐爆了。
構造內存溢出
1.定義一個 list
2.通過一個循環不停地往這個list里面添加對象
3.5 啟動項目,添加參數
瀏覽器驗證:
http://localhost:8080/heap
控制臺輸出:
Exception in thread “http-nio-12345-exec-3” java.lang.OutOfMemoryError: GC overhead limit exceeded
模擬內存溢出自動導出:
注:./指項目根目錄
控制臺輸出:
java.lang.OutOfMemoryError: GC overhead limit exceeded
Dumping heap to ./\java_pid12468.hprof …
Heap dump file created [44843683 bytes in 0.270 secs]
mat分析dump文件:
mat下載地址:
https://www.eclipse.org/mat/downloads.php
雙擊打開
很明顯在MemoryController中,有一個userList,在userList中User對象很多都沒有釋放。
CPU 線程 線程分析:
結果已經很明顯了,解決方案就是:釋放對象User就可以了
模擬使用jmap命令手動導出:
總結:理論上說:這2中都可以用,當內存很大的時候自動導出會導不出來,建議使用jmap手動導出即可
jmap -heap 3456
可以看到那一塊具體用了多少
上面是導出內存映像文件,下面來用MAT
分析內存溢出,內存映像文件到底存了什么東西?如何利用內存映像文件來定位內存溢出呢?
https://www.eclipse.org/downloads/download.php
jstack pid > pid.txt
sz pid.txt
線程狀態
top -p 15764 -H
https://docs.oracle.com/javase/8/docs/technotes/guides/troubleshoot
https://docs.oracle.com/javase/8/docs/technotes/guides/troubleshoot/tooldescr034.html
多么痛的領悟-代碼優化導致的BUG
blog.csdn.net/goldenfish1919/article/details/8755378
nohup java -jar monitor_tuuning-0.0.1-SNAPSHOT.jar &
10.5.6.142:12345/loop
top命令查看cpu負載,load acerage:
cpu負載變大請求就進不來了
解決方案:
jstack pid > pid pid.txt
sz pid.txt :下載命令
top -p pid -H:打印所有線程,篩選出占用cpu比較多的線程,看看占用cpu線程在干什么?
printf “%x” pid :線程pid
命令行pid是十進制的,導出的jstack 文件時十六進制的
10.5.6.142/deadlock
CATALINA_OPTS="$CATALINA_OPTS -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=8888 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -Djava.rmi.server.hostname=10.5.6.120"
JAVA_OPTS="$JAVA_OPTS -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=8888 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -Djava.rmi.server.hostname=10.5.6.120"
nohup java -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=8888 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -Djava.rmi.server.hostname=10.5.6.120 -jar monitor_tuuning-0.0.1-SNAPSHOT.jar &
tail -f nohup.out
jmap手動導出內存映像文件
命令行執行:
jmap -dump:format=b,file=heap.hprof 3456
格式:jmap -dump:format=b,file=heap.hprof pid
[root@localhost ~]# cd /app/nmonlogs/
[root@localhost nmonlogs]# ./nmon
按c查看CPU使用信息,按m查看內存使用信息,按n查看網絡使用信息
c
jmap -dump:format=b,file=heap.hprof 31322
總結
以上是生活随笔為你收集整理的jmap+MAT实战内存溢出的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 实战05_SSM整合ActiveMQ支持
- 下一篇: MyBatis-Plus_分页查询