什麼是記憶體泄漏,為什麼會導致記憶體溢出?
- 2020 年 7 月 10 日
- 筆記
工作一段時間後,會經常聽到記憶體溢出,那記憶體溢出到底是哪裡的記憶體溢出,是什麼原因導致的,如何解決,今天就來深入了解一下.
在java中,要了解記憶體,需要先清楚jvm記憶體模型,我們常說的java記憶體實際上就是指Runtime Data Area,分為虛擬機棧、堆、方法區、程式計數器、本地方法棧五個部分.這裡不做具體介紹.
1.常見的記憶體泄露
(1)記憶體分配未成功,卻使用了它
(2)記憶體分配成功,但尚未初始化就引用它
(3)記憶體分配成功且初始化,但操作越過了記憶體的邊界
(4)忘記釋放記憶體,造成記憶體泄漏
(5)釋放了記憶體卻繼續使用它
以發生的方式來分類:
(1)常發性記憶體泄漏,發生記憶體泄漏的程式碼會被多次執行到,每次執行都會導致一塊記憶體泄漏
(2)偶發性記憶體泄漏
(3)一次性記憶體泄漏,發送泄漏的程式碼只會被執行一次
(4)隱式記憶體泄漏,程式在運行過程中不停地分配記憶體,但直到結束時才釋放記憶體。
2.為什麼會導致記憶體溢出
編寫java程式最為方便的地方就是我們不需要管理記憶體的分配和釋放,一切由jvm來進行處理,當java對象不再被應用時,等到堆記憶體不夠用時,jvm會進行垃圾回收,清除這些對象佔用的堆記憶體空間,如果對象一直被應用,jvm無法對其進行回收,創建新的對象時,無法從Heap中獲取足夠的記憶體分配給對象,這時候就會導致記憶體溢出。而出現記憶體泄露的地方,一般是不斷的往容器中存放對象,而容器沒有相應的大小限制或清除機制。容易導致記憶體溢出。
3.如何發現記憶體泄漏
可以直接使用VisualVM,已在JDK6.0 update 7 中自帶,能夠監控執行緒,記憶體情況,查看方法的CPU時間和記憶體中的對 象,已被GC的對象,反向查看分配的堆棧.
如果要在伺服器上使用Java VisualVM, 比如CentOS。那麼就出現 WARNING: environment variable DISPLAY is not set,因為一般伺服器都不會裝X server。我們可以在遠程機器上裝一個X server,比如windwos上,那麼就可以非常方便的查看伺服器運行情況。
如果有大量的FGC就要查詢是否有記憶體泄漏的問題了,圖中的FGC數量就比較大,並且執行時間較長,這樣就會導致系統的響應時間較長,如果對jvm的記憶體設置較大,那麼執行一次FGC的時間可能會更長。(直接運行linux上的jvisualvm,下載X-Manager,可以將視圖展現在本地機器上。)
從上圖可以發現執行FGC的情況,下午3:10分之前是沒有FGC的,之後出現大量的FGC。
上圖是jvm堆記憶體的使用情況,下午3:10分之前的記憶體回收還是比較合理,但是之後大量記憶體無法回收,最後導致記憶體越來越少,導致大量的full gc。
4.如何定位記憶體泄漏
![](http://images2015.cnblogs.com/blog/159373/201606/159373-20160610115522793-1965619037.png)
![](http://images2015.cnblogs.com/blog/159373/201606/159373-20160610115545121-1995147626.png)
![](http://images2015.cnblogs.com/blog/159373/201606/159373-20160610115607558-2090088130.png)
![](http://images2015.cnblogs.com/blog/159373/201606/159373-20160610115624027-1946144388.png)
![](http://images2015.cnblogs.com/blog/159373/201606/159373-20160610115640277-1445113398.png)
![](http://images2015.cnblogs.com/blog/159373/201606/159373-20160610115714371-1611672342.png)
![](http://images2015.cnblogs.com/blog/159373/201606/159373-20160610115800996-1873172240.png)
![](http://images2015.cnblogs.com/blog/159373/201606/159373-20160610115932808-1186046269.png)
![](http://images2015.cnblogs.com/blog/159373/201606/159373-20160610115952621-342074884.png)
![](http://images2015.cnblogs.com/blog/159373/201606/159373-20160610120011808-1320353587.png)