日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

一次恐怖的 Java 内存泄漏排查实战

發布時間:2023/12/3 java 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 一次恐怖的 Java 内存泄漏排查实战 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

轉載自??一次恐怖的 Java 內存泄漏排查實戰

最近在看《深入理解Java虛擬機:JVM高級特性與最佳實踐》(第二版)這本書,理論+實踐結合,深入淺出,強烈推薦給大家。


這兩天對JVM內容進行了一個討論,討論的內容主要包括如下幾個方面。
1)內存溢出和內存泄露的介紹?
2)如何排查和處理內存泄露?

?

一、內存溢出和內存泄露

一種通俗的說法。
1、內存溢出:你申請了10個字節的空間,但是你在這個空間寫入11或以上字節的數據,出現溢出。
2、內存泄漏:你用new申請了一塊內存,后來很長時間都不再使用了(按理應該釋放),但是因為一直被某個或某些實例所持有導致 GC 不能回收,也就是該被釋放的對象沒有釋放。點擊此處查看內存泄漏更多說明。

?

下面具體介紹。

1.1 內存溢出

java.lang.OutOfMemoryError,是指程序在申請內存時,沒有足夠的內存空間供其使用,出現OutOfMemoryError。點擊此處查看內存泄漏更多說明。


產生原因
產生該錯誤的原因主要包括:

  • JVM內存過小。

  • 程序不嚴密,產生了過多的垃圾。

    ?

程序體現
一般情況下,在程序上的體現為

  • 內存中加載的數據量過于龐大,如一次從數據庫取出過多數據。

  • 集合類中有對對象的引用,使用完后未清空,使得JVM不能回收。

  • 代碼中存在死循環或循環產生過多重復的對象實體。

  • 使用的第三方軟件中的BUG。

  • 啟動參數內存值設定的過小。

    ?

錯誤提示
此錯誤常見的錯誤提示:

tomcat:java.lang.OutOfMemoryError: PermGen space tomcat:java.lang.OutOfMemoryError: Java heap space weblogic:Root cause of ServletException java.lang.OutOfMemoryError resin:java.lang.OutOfMemoryError java:java.lang.OutOfMemoryError

?

解決方法

1)增加JVM的內存大小
對于tomcat容器,找到tomcat在電腦中的安裝目錄,進入這個目錄,然后進入bin目錄中,在window環境下找到bin目錄中的catalina.bat,在linux環境下找到catalina.sh。
編輯catalina.bat文件,找到JAVA_OPTS(具體來說是?set "JAVA_OPTS=%JAVA_OPTS% %LOGGING_MANAGER%")這個選項的位置,這個參數是Java啟動的時候,需要的啟動參數。
也可以在操作系統的環境變量中對JAVA_OPTS進行設置,因為tomcat在啟動的時候,也會讀取操作系統中的環境變量的值,進行加載。
如果是修改了操作系統的環境變量,需要重啟機器,再重啟tomcat,如果修改的是tomcat配置文件,需要將配置文件保存,然后重啟tomcat,設置就能生效了。

2)優化程序,釋放垃圾
主要思路就是避免程序體現上出現的情況。避免死循環,防止一次載入太多的數據,提高程序健壯型及時釋放。因此,從根本上解決Java內存溢出的唯一方法就是修改程序,及時地釋放沒用的對象,釋放內存空間。

?

1.2?內存泄露

Memory Leak,是指程序在申請內存后,無法釋放已申請的內存空間,一次內存泄露危害可以忽略,但內存泄露堆積后果很嚴重,無論多少內存,遲早會被占光。


在Java中,內存泄漏就是存在一些被分配的對象,這些對象有下面兩個特點。
1)首先,這些對象是可達的,即在有向圖中,存在通路可以與其相連;
2)其次,這些對象是無用的,即程序以后不會再使用這些對象。


如果對象滿足這兩個條件,這些對象就可以判定為Java中的內存泄漏,這些對象不會被GC所回收,然而它卻占用內存。

關于內存泄露的處理頁就是提高程序的健壯型,因為內存泄露是純代碼層面的問題。點擊此處查看內存泄漏更多說明。

?

1.3 內存溢出和內存泄露的聯系

內存泄露會最終會導致內存溢出。

相同點:都會導致應用程序運行出現問題,性能下降或掛起。
不同點:1) 內存泄露是導致內存溢出的原因之一,內存泄露積累起來將導致內存溢出。2) 內存泄露可以通過完善代碼來避免,內存溢出可以通過調整配置來減少發生頻率,但無法徹底避免。

?

二、一個Java內存泄漏的排查案例

某個業務系統在一段時間突然變慢,我們懷疑是因為出現內存泄露問題導致的,于是踏上排查之路。

2.1?確定頻繁Full GC現象

首先通過“虛擬機進程狀況工具:jps”找出正在運行的虛擬機進程,最主要是找出這個進程在本地虛擬機的唯一ID(LVMID,Local Virtual Machine Identifier),因為在后面的排查過程中都是需要這個LVMID來確定要監控的是哪一個虛擬機進程。


同時,對于本地虛擬機進程來說,LVMID與操作系統的進程ID(PID,Process Identifier)是一致的,使用Windows的任務管理器或Unix的ps命令也可以查詢到虛擬機進程的LVMID。


jps命令格式為:
jps [ options ] [ hostid ]
使用命令如下:
使用jps:jps -l


使用ps:ps aux | grep tomat?找到你需要監控的ID(假設為20954),再利用“虛擬機統計信息監視工具:jstat”監視虛擬機各種運行狀態信息。

?

jstat命令格式為:
jstat [ option vmid [interval[s|ms] [count]] ]
使用命令如下:
jstat -gcutil 20954 1000
意思是每1000毫秒查詢一次,一直查。gcutil的意思是已使用空間站總空間的百分比。


結果如下圖:

?

?

jstat執行結果

查詢結果表明:這臺服務器的新生代Eden區(E,表示Eden)使用了28.30%(最后)的空間,兩個Survivor區(S0、S1,表示Survivor0、Survivor1)分別是0和8.93%,老年代(O,表示Old)使用了87.33%。程序運行以來共發生Minor GC(YGC,表示Young GC)101次,總耗時1.961秒,發生Full GC(FGC,表示Full GC)7次,Full GC總耗時3.022秒,總的耗時(GCT,表示GC Time)為4.983秒。

?

2.2?找出導致頻繁Full GC的原因

分析方法通常有兩種:
1)把堆dump下來再用MAT等工具進行分析,但dump堆要花較長的時間,并且文件巨大,再從服務器上拖回本地導入工具,這個過程有些折騰,不到萬不得已最好別這么干。


2)更輕量級的在線分析,使用“Java內存影像工具:jmap”生成堆轉儲快照(一般稱為headdump或dump文件)。
jmap命令格式:
jmap [ option ] vmid
使用命令如下:
jmap -histo:live 20954
查看存活的對象情況,如下圖所示:

?

?

存活對象

按照一位IT友的說法,數據不正常,十有八九就是泄露的。在我這個圖上對象還是挺正常的。

我在網上找了一位博友的不正常數據,如下:

?

可以看出HashTable中的元素有5000多萬,占用內存大約1.5G的樣子。這肯定不正常。

?

2.3 定位到代碼

定位帶代碼,有很多種方法,比如前面提到的通過MAT查看Histogram即可找出是哪塊代碼?!乙郧笆鞘褂眠@個方法。也可以使用BTrace,我沒有使用過。

創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

總結

以上是生活随笔為你收集整理的一次恐怖的 Java 内存泄漏排查实战的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。