天天看點

分析解決OOM與JVM參數調優

一.OOM存在的幾種情況.

除了程式計數器外,虛拟機記憶體的其他幾個運作時區域都可能發OOM.隻不過堆記憶體溢出最為常見.

1, 堆記憶體溢出

一般的異常資訊:java.lang.OutOfMemoryError:Java heap spacess

   java堆用于存儲對象執行個體,我們隻要不斷的建立對象,并且保證GC Roots到對象之間有可達路徑來避免垃圾回收機制清除這些對象,就會在對象數量達到最大堆容量限制後産生記憶體溢出異常。

2, 虛拟機棧和本地方法棧溢出

   如果線程請求的棧深度大于虛拟機所允許的最大深度,将抛出StackOverflowError異常。

   如果虛拟機在擴充棧時無法申請到足夠的記憶體空間,則抛出OutOfMemoryError異常

   這裡需要注意當棧的大小越大可配置設定的線程數就越少。

3, 運作時常量池溢出

異常資訊:java.lang.OutOfMemoryError:PermGen space

   如果要向運作時常量池中添加内容,最簡單的做法就是使用String.intern()這個Native方法。該方法的作用是:如果池中已經包含一個等于此String的字元串,則傳回代表池中這個字元串的String對象;否則,将此String對象包含的字元串添加到常量池中,并且傳回此String對象的引用。由于常量池配置設定在方法區内,我們可以通過-XX:PermSize和-XX:MaxPermSize限制方法區的大小,進而間接限制其中常量池的容量。

4, 方法區溢出

異常資訊:java.lang.OutOfMemoryError:PermGen space

   方法區用于存放Class的相關資訊,如類名、通路修飾符、常量池、字段描述、方法描述等。

   方法區溢出也是一種常見的記憶體溢出異常,一個類如果要被垃圾收集器回收,判定條件是很苛刻的。在經常動态生成大量Class的應用中,要特别注意這點。

二.堆記憶體溢出檢查.

1.在程式啟動時我們可以設定以下參數以便在記憶體溢出時生成dump檔案:

   -XX:Xms20m;

    -XX:Xms20m:

    -XX:+HeapDumpOnOutOfMemoryError

    -XX:HeapDumpPath=D:/(注意這裡沒有加号)

以上的指令是已經發生記憶體溢出的時候我們配置讓其輸出溢出資訊.在實際工作中不可能等到真正溢出再去處理,會實時監控資料.

2.使用jmap實時檢視記憶體情況/導出dump檔案

一般來說有以下幾步:

    (1).jps -l:找到目前程序id.

    (2).jmap -heap pid:檢視目前程序的資料.(老年代新生代的使用情況)

    (3).jmap -dump:format=b,file=app.hprof pid(導出該程序的hprof的檔案,關于記憶體情況的映射)

說明:file後面跟的是檔案名稱,檔案路徑自動生成,顯示在cmd中,去對應路徑中找檔案即可.

三.設定新生代和老年代記憶體比例.

1.這個參數對系統性能以及GC行為有很大影響,新生代一般設定整個堆空間的1/3-1/4.

    -Xmn10m: 設定新生代初始大小為10m.

2.-XX:SurvivorRatio:用來設定新生代中eden空間和from/to空間的比例.

    也就是-XX:SurvivorRatio=eden/from=eden/to

    舉例:-Xmn10m -XX:SurvivorRatio=2 那麼eden5m,from和t各2.5m

3.-XX:NewRatio=老年代/新生代

    設定老年代和新生代比例.

基本政策:盡可能将對象預留在新生代,減少老年代的GC次數.

四.Java程序CPU占用過高檢查.

分析解決OOM與JVM參數調優