Java中,通過“垃圾回收”機制雖然能夠將
無用的對象從內存中刪除,但前提是僅當該對象不再被引用時才會被統計為無用的。
內存泄漏的常見表現:
·日志中頻繁出現“OutOfMemoryException”內存溢出錯誤;
·系統不時宕機;
·使用分析工具發現↓
內存回收低位點不斷升高(以每次內存回收的最低點連成一條直線,那么它是一條上升線);
內存回收的頻率也越來越高,內存占用也越來越高,最終出現"OutOfMemoryException"的系統異常。
內存泄漏的原因:
java把內存分兩種:一種是棧內存,另一種是堆內存
1.在函數中定義的基本類型變量和對象的引用變量都在函數的棧內存中分配;
2.堆內存用來存放由new創建的對象和數組;
在函數(代碼塊)中定義一個變量時,java就在棧中為這個變量分配內存空間,當超過變量的作用域后,java會自動釋放掉為該變量所分配的內存空間;
在堆中分配的內存由java虛擬機的自動垃圾回收器來管理。
堆的優勢是可以動態分配內存大小,生存期也不必事先告訴編譯器,因為它是在運行時動態分配內存的。缺點就是要在運行時動態分配內存,存取速度較慢;
棧的優勢是存取速度比堆要快,缺點是存在棧中的數據大小與生存期必須是確定的無靈活性。
如何分析:
1.代碼走查和分析,找出程序中潛在的問題代碼;
2.使用專門的內存泄漏測試工具找出內存泄漏發生的位置;
工具的使用↓
·抓取不同時刻的內存快照;
·捕獲堆上的數據;
·強制執行GC,以便觀察受懷疑的類實例是否會被作為垃圾收集;
·能顯示出類實例的引用鏈;
推薦使用Eclipse的插件MAT(Memory Analyzer Tool)來幫助迅速,準確地分析內存泄漏;
一般說來,一個正常的系統在其運行穩定后其內存的占用量是基本穩定的,不應該是無限制的增長的,同樣,
對任何一個類的對象的使用個數也有一個相對穩定的上限,不應該是持續增長的。根據這樣的基本假設,我
們可以持續地觀察系統運行時使用的內存的大小和各實例的個數,如果內存的大小持續地增長,則說明系統
存在內存泄漏,如果某個類的實例的個數持續地增長,則說明這個類的實例可能存在泄漏情況。
分析步驟:
·使用內存快照進行數據收集;
·初步分析,判斷是否存在內存泄漏;
·分析定位,找到被泄漏的對象;
·修正錯誤再測試驗證;