OOM的三種類型:
堆OOM
/**
* -Xmx1g -XX:+PrintGCDetails -XX:MaxDirectMemorySize=100m
*
* @param args
*/
public static void main(String[] args) { ArrayList<byte[]> arrayList = new ArrayList<>(); for (int i =
運作結果:
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space at com.Test.main(Test.java:15)
解決方法: 增大Xmx值 使用MAT,JProfile等工具進行代碼分析與優化
直接記憶體OOM
/**
* -Xmx1g -XX:+PrintGCDetails -XX:MaxDirectMemorySize=100m
* @param args
*/
public static void main(String[] args) { for (int i =
運作結果:
直接記憶體設定為2M,超過100M時,進行回收
解決方法: 增大MaxDirectMemorySize的值
過多線程導緻的OOM
/**
* -Xmx1g -XX:+PrintGCDetails
-XX:MaxDirectMemorySize=100m
-Xss:指定棧空間大小
*
* @param args
*/
public static void main(String[] args) { for (int i =
運作結果:
OOM unable to create native thread
解決方法: 減少線程數、或減少堆空間與線程空間
永久(Pern)溢出
永久區是存儲類中繼資料的區域
/**
* -Xmx1g -XX:+PrintGCDetails
*
* @param args
*/
public static void main(String[] args) { for (int i =
運作結果:
OOM Permgen sace
解決方法:
- 增大MaxPremSize的值
- 減少系統需要的類的數量
- 使用ClassLoader合理裝載類,并進行回收
GC效率低下引起的OOM
判斷GC引起OOM的條件
- 花在GC上的時間是否超過了98%
- 老年代釋放的記憶體是否小于2%
- Eden區釋放的記憶體是否小于2%
- 是否連續5次GC都出現了上述幾種情況
關閉OOM可以通過參數:-XX:-UseGCOverheadLimit 進行設定
String常量池因其的OOM
/**
* -Xmx5m -XX:MaxPermSize5m【JDK<1.6】
*
* @param args
*/
public static void main(String[] args) { List<String> list = new ArrayList<>(); int i =
運作結果:
JDK1.6
:Perm space
JDK1.7
:heap space
【注】
/**
*String.intern()方法傳回字元串常量池引用,但不一定每時每刻都傳回一樣,可能垃圾回收後重新放入常量池
*
* @param args
*/
public static void main(String[] args) {
System.out.println(System.identityHashCode((args[
淺堆和深堆
淺堆(shallow heap):一個對象結構所占的記憶體大小,對象包括屬性和對象頭、對象引用等。
如String對象,其結構包括:
類型 | 值 | 大小 |
---|---|---|
int | hash32 | |
int | hash | |
ref | value | c://... |
其中2個int8位元組 對象引用4位元組 對象頭8位元組 按照8位元組對齊,則對象淺堆共24位元組
深堆(retained heap):一個對象被GC回收後,可以真實釋放的記憶體大小。即對象所持有的對象和包括對象自身的所有的淺堆的大小之和。
從圖中可以看出對象A的淺堆大小為A本身,對象A的實際大小為對象A、對象B、對象C、對象D的淺堆大小之和,對象A的深堆大小為對象A和對象C,因為對象B和對象D同時也被對象E所引用
轉載于:https://www.cnblogs.com/htkj/p/10932489.html