Java內存溢出和內存泄露后怎么解決


1.首先這里先說一下內存溢出和內存泄露的區別:

內存溢出 out of memory,是指程序在申請內存時,沒有足夠的內存空間供其使用,出現out of memory;比如申請了一個integer,但給它存了long才能存下的數,那就是內存溢出。

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

memory leak會最終會導致out of memory!

2.我們這里做一個內存溢出的例子

/**
 * VM Args:-Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError
 * @author Administrator
 *
 */

public class TestDump {

    static class OOB {

    }

    public static void main(String[] args) {
        List<OOB> list = new ArrayList<OOB>();
        while (true) {
            list.add(new OOB());
        }
    }

}

其中-Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError是需要加的JVM啟動參數

-Xms20m將堆的最小值設置為20MB,-Xmx20m將堆的最大值設置為20MB,當設置一樣時即可避免堆自動擴展。

-XX:+HeapDumpOnOutOfMemoryError可以讓虛擬機在內存溢出時Dump當前的內存堆轉儲快照以便事后進行分析。

運行結果:

java.lang.OutOfMemoryError: Java heap space
Dumping heap to java_pid6256.hprof ...
Heap dump file created [27904625 bytes in 0.098 secs]
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at java.util.Arrays.copyOf(Arrays.java:2245)
    at java.util.Arrays.copyOf(Arrays.java:2219)
    at java.util.ArrayList.grow(ArrayList.java:242)
    at java.util.ArrayList.ensureExplicitCapacity(ArrayList.java:216)
    at java.util.ArrayList.ensureCapacityInternal(ArrayList.java:208)
    at java.util.ArrayList.add(ArrayList.java:440)
    at com.webservie.TestDump.main(TestDump.java:18)

異常信息java.lang.OutOfMemoryError: Java heap space。解決該區域問題,一般先通過內存印象分析工具(如Eclipse Memory Analyzer)對Dump出來的堆轉儲快照進行分析,重點是確認內存中的對象是否是必要的,

要就是先要分清楚到底是出現了內存泄露還是內存溢出。

java_pid6256.hprof就是生成的快照,可以在類所在的工程根目錄下找到。

打開該快照文件,如圖所示:

如果是內存泄露,可進一步通過工具查看泄露對象到GC Roots的引用鏈。於是就能找到泄露對象是通過怎樣的路徑與GC Roots相關聯並導致垃圾收集器無法自動回收它們的。

掌握了泄露對象的類型信息及GC Roots引用鏈的信息,就可以比較准確的定位出泄露代碼的位置。

如果不存在泄露,就是內存中的對象確實都還必須存活着,就應該檢測虛擬機的堆參數(-Xmx和-Xms),與機器物理內存對比,看看是否可以調大,從代碼上檢查是否存在某些

對象生命周期過長、持有狀態時間過長的情況,嘗試減少程序運行期的內存消耗。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM