1、java.lang.StackOverflowError
- 在一個函數中調用自己就會產生這樣的錯誤(棧溢出)
- 發生區域:java虛擬機棧或本地方法棧
public class StackOverFlowErrorDemo {
public static void main(String[] args) {
stackOverFlowError();
}
public static void stackOverFlowError(){
stackOverFlowError();
}
}
2、java.lang.OutOfMemoryError: Java heap space
- new 一個很大對象
- 發生區域:java堆
/**
* -Xms10m -Xmx10m
*/
public class JavaHeapSpaceDemo {
static class OOMObject{
}
public static void main(String[] args) {
List<OOMObject> list = new ArrayList<>();
while (true){
list.add(new OOMObject());
}
}
}
3、java.lang.OutOfMemoryError: GC overhead limit exceeded
- GC回收時間過長,超過98%的時間用來做GC,並且回收了不到2%的堆內存
/**
* -Xms10m -Xmx10m -XX:+PrintGCDetails -XX:MaxDirectMemorySize=5m
*/
public class GCoverheadDemo {
public static void main(String[] args) {
int i = 0;
List<String> list = new ArrayList<>();
while (true) {
list.add(String.valueOf(++i).intern());
}
}
}
4、java.lang.OutOfMemoryError: Direct buffer memory
原因:直接內存不足
寫NIO程序經常使用ByteBuffer來讀取或寫入數據,這是一種基於通道與緩沖區的I/O方式
ByteBuffer.allocate() 分配JVM堆內存,屬於GC管轄范圍,需要拷貝所以速度相對較慢
ByteBuffer.allocateDirect() 分配操作系統本地內存,不屬於GC管轄范圍,不需要內存拷貝所以速度相對較快
/**
* -Xms10m -Xmx10m -XX:+PrintGCDetails -XX:MaxDirectMemorySize=5m
*/
public class DirectBufferMemoryDemo {
public static void main(String[] args) throws InterruptedException {
System.out.println("maxDirectMemory : " + sun.misc.VM.maxDirectMemory() / 1024 / 1024 + "MB");
TimeUnit.SECONDS.sleep(1);
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(6 * 1024 * 1024);
}
}
5、java.lang.OutOfMemoryError : unable to create new native thread
- 一個應用進程創建了多個線程,超過系統承載極限,Linux默認允許單個進程可以創建的線程數1024
/**
* 一個應用進程創建了多個線程,超過系統承載極限,Linux默認是1024
*/
public class UnableCreateNewThreadDemo {
public static void main(String[] args) {
for (int i = 0; ; i++) {
new Thread(() -> {
try {
Thread.sleep(Integer.MAX_VALUE);
} catch (InterruptedException e) {
e.printStackTrace();
}
}, String.valueOf(i)).start();
}
}
}
linux系統下:
ulimit -u --查看線程上限 cat /etc/security/limits.d/20-nproc.conf
6、java.lang.OutOfMemoryError: Metaspace
java8使用Metaspace代替永久代,與永久代最大的區別是:元空間並不在虛擬機內存中,而是使用本地內存。
永久代(java8使用Metaspace)存放的信息:
- 虛擬機加載的類信息
- 常量池
- 靜態變量
- 即時編譯后的代碼
/**
* 不斷生成類往元空間推,類占據的空間總是會超過Metaspace的大小
* -XX:MetaspaceSize=8m -XX:MaxMetaspaceSize=8m
*/
public class MetaspaceOOMDemo {
static class OOMTest {
}
public static void main(String[] args) {
int i = 0; //模擬計數多少次后發生了異常
try {
while (true) {
i++;
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(i + "次后發送了異常");
e.printStackTrace();
}
}
}
