工作一段時間后,會經常聽到內存溢出,那內存溢出到底是哪里的內存溢出,是什么原因導致的,如何解決,今天就來深入了解一下.
在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.如何定位內存泄漏









