這篇文章主要匯總了Java虛擬機常見的記憶體溢位錯誤,警示大家,避免出錯,感興趣的朋友可以了解下
一、引言
從事java開發的小伙伴在平時的開發作業中,應該會遇見各式各樣的例外和錯誤,在實際作業中積累的例外或者錯誤越多,趟過的坑越多,就會使我們編碼更加的健壯,就會本能地避開很多嚴重的坑,以下介紹幾個Java虛擬機常見記憶體溢位錯誤,以此警示,避免生產血案,
最新2020整理收集的一些面試題(都整理成檔案),有很多干貨,包含netty,spring,執行緒,spring cloud等詳細講解,也有詳細的學習規劃圖,面試題整理等,我感覺在面試這塊講的非常清楚:獲取面試資料只需:點擊這里領取!!! 暗號:CSDN
二、模擬Java虛擬機常見記憶體溢位錯誤
1、記憶體溢位之堆疊溢位錯誤
package com.jayway.oom;
/**
* 堆疊溢位錯誤
* 虛擬機引數:-Xms10m -Xmx10m
* 拋出例外:Exception in thread "main" java.lang.StackOverflowError
*/
public class StackOverflowErrorDemo {
public static void main(String[] args) {
stackOverflowError();
}
private static void stackOverflowError() {
stackOverflowError();
}
}
2、記憶體溢位之堆溢位錯誤
package com.jayway.oom;
import java.util.Random;
/**
* 堆溢位錯誤
* 虛擬機引數:-Xmx10m -Xms10m
* 拋出例外:Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
*/
public class JavaHeapSpaceErrorDemo {
public static void main(String[] args) {
String temp = "java";
//不斷地在堆中開辟空間,創建物件,撐爆堆記憶體
while (true) {
temp += temp + new Random().nextInt(111111111) + new Random().nextInt(222222222);
temp.intern();
}
}
}
3、記憶體溢位之GC超過執行限制錯誤
package com.jayway.oom;
import java.util.ArrayList;
import java.util.List;
/**
- GC超過執行限制錯誤
- 虛擬機引數:-Xms10m -Xmx10m -XX:+PrintGCDetails -XX:MaxDirectMemorySize=5m
-
- 拋出例外:Exception in thread “main” java.lang.OutOfMemoryError: GC overhead limit exceeded
-
- 導致原因:GC回收時間過長會拋出OutOfMemoryError,何為過長,即超過98%的cpu時間用來做GC垃圾回收
- 但是回收效果甚微,僅僅只有2%的CPU時間用來用戶程式的作業,這種狀態是很糟糕的,程式在不斷地GC
- 形成惡性回圈,CPU的使用率一直是滿負荷的,正經活卻沒有干,這種情況虛擬機只好拋出錯誤來終止程式的執行
- 不斷地Full GC,事倍功微
- [Full GC (Ergonomics) [PSYoungGen: 2047K->2047K(2560K)] [ParOldGen: 7167K->7161K(7168K)] 9215K->9209K(9728K), [Metaspace: 3529K->3529K(1056768K)], 0.0291829 secs] [Times: user=0.08 sys=0.02, real=0.03 secs]
*/
public class GCOverheadErrorDemo {
public static void main(String[] args) {
int i = 0;
List<String> list = new ArrayList<>();
try {
while (true) {
list.add(String.valueOf(++i).intern());
}
} catch (Throwable e) {
System.out.println("*****************i:" + i);
e.printStackTrace();
throw e;
}
}
}
4、記憶體溢位之直接記憶體溢位錯誤
package com.jayway.oom;
import java.nio.ByteBuffer;
/**
- 直接記憶體溢位錯誤
- 拋出例外:Exception in thread “main” java.lang.OutOfMemoryError: Direct buffer memory
-
- 配置虛擬機引數:-Xms10m -Xmx10m -XX:+PrintGCDetails -XX:MaxDirectMemorySize=5m
-
- 導致原因:通常NIO程式經常使用ByteBuffer來讀取或者寫入資料,這是一種基于通道(Channel)與緩沖區(Buffer)的IO方式,
- 它可以使用Native函式庫直接分配堆外記憶體,然后通過一個存盤在java堆里面的DirectByteBuffer物件作為這塊記憶體的參考,
- 這樣能子一些場景中顯著提高性能,因為避免了在Java堆和Native記憶體中來回復制資料,
- ByteBuffer.allocate(capability):分配JVM堆記憶體,資料GC的管轄范圍,由于需要拷貝所以速度相對較慢
- ByteBuffer.allocate(capability):分配OS本地記憶體,不屬于GC管轄范圍,由于不需要記憶體拷貝,所以速度相對較快,
- 但是如果不斷分配本地記憶體,堆記憶體很少使用,那么JVM就不需要執行GC,DirectByteBuffer物件就不會被回收,此時如果繼續分配堆外記憶體,
- 可能堆外記憶體已經被耗光了無法繼續分配,此時程式就會拋出OutOfMemoryError,直接崩潰,
*/
public class DirectBufferMemoryErrorDemo {
public static void main(String[] args) {
//默認JVM配置的最大直接記憶體是總物理記憶體的四分之一
long maxDirectMemory = sun.misc.VM.maxDirectMemory() / 1024 / 1024;
System.out.println("配置的maxDirectMemory:" + maxDirectMemory + "MB");
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(6 * 1024 * 1024);
}
}
5、記憶體溢位之無法創建新的本地執行緒
package com.jayway.oom;
/**
* 記憶體溢位之無法創建新的本地執行緒
* 拋出例外:java.lang.OutOfMemoryError: unable to create new native thread
-
- 描述:
- 高并發請求服務器時,經常出現java.lang.OutOfMemoryError: unable to create new native thread
- native thread例外與對應的平臺有關
- 導致原因:
- 1、應用程式創建了太多執行緒了,一個應用行程創建的執行緒數超過系統承載極限,
- 2、作業系統并不允許你的應用行程創建這么多的執行緒,linux系統默認允許單個行程可以創建的執行緒數是1024個
- 解決方法:
- 1、想辦法降低應用行程創建的執行緒數量,
- 2、如果應用程式確實需要這么多執行緒,超過了linux系統的默認1024個限制,可以通過修改linux服務器配置,提高這個閾值,
*/
public class UnableCreateNativeThreadErrorDemo {
public static void main(String[] args) {
for (int i = 0; true; i++) {
System.out.println("***************i:" + i);
//不斷得創建新執行緒,直到超過作業系統允許應用行程創建執行緒的極限
new Thread(() -> {
try {
Thread.sleep(Integer.MAX_VALUE);
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
}
}
}
6、記憶體溢位之元空間溢位錯誤
package com.jayway.oom;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
/**
- 元空間溢位錯誤
- 拋出例外:java.lang.OutOfMemoryError: Metaspace
-
- 設定虛擬機引數:-XX:MetaspaceSize=8m -XX:MaxMetaspaceSize=8m
-
- 描述:Java8及以后的版本使用Metaspace來替代了永久代,metaspace是方法區在HotSpot中的實作,它與持久代最大的區別在于
- Metaspace并不在虛擬機記憶體中而是在本地記憶體中,
- 元空間存盤了以下資訊:
- 1、虛擬機加載的類資訊
- 2、常量池
- 3、靜態變數
- 4、即時編譯后的代碼
*/
public class MetaspaceErrorDemo {
static class OOMTest {
}
public static void main(String[] args) {
int count = 0;
try {
//cglib不斷創建類,模擬Metaspace空間溢位,我們不斷生成類往元空間中灌,超過元空間大小后就會拋出元空間移除的錯誤
while (true) {
count++;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(OOMTest.class);
enhancer.setUseCache(false);
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
return methodProxy.invokeSuper(o, args);
}
});
enhancer.create();
}
} catch (Throwable e) {
System.out.println("************多少次后發生了例外:" + count);
e.printStackTrace();
}
}
}
三、總結
以上就是Java虛擬機常見記憶體溢位錯誤匯總的詳細內容,作為一枚Java程式員真的是太強大了,除了要解決日常的bug還要對付這么多莫名其妙的陷阱,一不小心就掉坑里了,損失的都是自己的頭發啊,~~Java中常見的坑還有很多,由于篇幅過長就不一 一展現了,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/184864.html
標籤:其他
上一篇:Java基礎——面向物件和類
