您好,登錄后才能下訂單哦!
這篇文章將為大家詳細講解有關JAVA中怎么排查內存泄漏,文章內容質量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關知識有一定的了解。
內存泄漏
內存泄漏(Memory Leak)是指程序中一個對象或變量無法回收,一直保存在內存中。這樣的對象或變量一直累計,最終導致內存溢出(Out Of Memory)。
內存泄漏原因
內存泄漏大概有以下幾個原因
1.靜態集合存放對象
長周期對象持有了短周期的對象的引用,就可能導致內存泄漏。如果集合是靜態的,那么該集合的生命周期就和程序的生命周期一致。且對象存放在靜態集合中,所以在整個程序的生命周期內,對象都無法被釋放,最終導致內存泄漏。
2.連接未關閉
數據庫連接,網絡連接,IO連接等生成連接后,如果沒有調用close方法,則會造成相關的對象無法被回收,導致內存泄漏。
3.單例對象
單例對象的生命周期和程序的生命周期也是一致的,所以如果單例對象引用了一個外部對象,那么這個外部對象在程序結束前也是無法被釋放的。存在內存泄漏的風險。
4.改變對象HASH值
如果一個對象被存入HashSet集合,再修改對象參與Hash值計算的屬性,那么對象的Hash值就會改變。由于對象存入HashSet集合時存放的位置是根據舊Hash值獲得的,那么當Hash變動后,已經找不回原來的位置,這就導致這個對象無法在HashSet被搜索到,也無法被刪除。由于一直存在于HashSet,那么除非HashSet被釋放,否則該對象將一直被HashSet引用,從而無法被釋放,造成內存泄漏。
5.內部類持有外部類引用
如果一個內部類調用了一個外部類的方法,并且將內部類作為參數傳遞過去。那么如果外部類不釋放這個內部類,這個內部類就無法釋放,就可能造成內存泄漏。
排查步驟
1.通過jps命令找出正在執行的虛擬機進程,獲取進程的在虛擬機中的唯一ID,命令格式如下:
Jps [options] [hostid]
例如 jps -l,結果如下:
options的參數如下:
-q | 不輸出類名、Jar名和傳入main方法的參數 |
-m | 輸出傳入main方法的參數 |
-l | 輸出main類或Jar的權限名 |
-v | 輸出傳入JVM的參數 |
hostid可以用來查看其他服務器上虛擬器的進程,默認是本機
2.獲取唯一ID,可以使用jstat監視進程狀態,命令格式如下:
Jstat [option vmid [interval[s|ms] [count]]]
例如 jstat -gc 12116 1000 4
每隔1000毫秒查詢某個進程的已使用空間占總空間百分比,總共查4次,結果如下
S0C | 生存區0容量 |
S1C | 生存區1容量 |
S0U | 生存區0使用量 |
S1U | 生存區1使用量 |
EC | Eden區容量 |
EU | Eden區使用量 |
OC | 老年代容量 |
OU | 老年代使用量 |
MC | 方法區容量 |
MU | 方法區使用量 |
CCSC | 壓縮類空間容量 |
CCSU | 壓縮類空間使用量 |
YGC | 年輕代GC次數 |
YGCT | 年輕代GC耗時 |
FGC | FULL GC 次數 |
FGCT | FULL GC 耗時 |
GCT | GC總耗時 |
option的參數如下
-class | 顯示加載class的數量,及所占空間等信息 |
-compiler | 顯示VM實時編譯的數量等信息 |
-gc | 可以顯示gc的信息,查看gc的次數,及時間 |
-gccapacity | 可以顯示VM內存中三代(young,old,perm)對象的使用和占用大小 |
-gcutil | 統計gc信息 |
-gcnew | 年輕代對象的信息 |
-gcnewcapacity | 年輕代對象的信息及占用量 |
-gcold | old代對象的信息 |
-gcoldcapacity | old代對象的信息及占用量 |
-gcpermcapacity | perm對象的信息及占用量 |
-printcompilation | 當前VM執行的信息 |
3.可以使用jmap分析堆內存使用情況,命令格式如下:
jmap [option] pid
例如:jmap -histo:live 6088,結果如下
沒有參數打印進程的類加載器和類加載器加載的持久代對象
option的參數如下
-heap | 查看進程堆內存使用情況,包括使用的GC算法、堆參數配置和各代中堆內存的使用情況 |
-histo | 查看堆內存中的對象數目、大小統計 |
-histo:live | 查看堆內存中活的對象數目、大小統計,并進行一次GC |
-dump:format=b,file=dumpFileName | 用jmap把進程內存使用情況dump到文件中 |
通過檢查類的占用情況可以分析是哪個類出現了內存泄漏,實在不行,也可以通過dump命令生成dump文件進一步分析。
例如
jmap -dump:format=b,file=20210512.dump 6088
然后使用jvisualvm工具分析dump文件
關于JAVA中怎么排查內存泄漏就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。