目录
1 java.lang.StackOverflowError 栈空间撑爆
1.2 StackOverflowError是异常还是错误(Error/Exception)
2 java.lang.OutOfMemoryError: Java heap space
3 java.lang.OutOfMemoryError: GC ovverhead limit exceeded
4 java.lang.OutOfMemoryError: Direct bufffer memory
4.1 DEMO-Direct bufffer memory
5 java.lang.OutOfMemoryError: unable to create new native thread
5.1 DEMO-线程过多(在LINUX运行此程序代码,windows测试的时候要很久)
6 java.lang.OutOfMemoryError:Metaspace
- java.lang.StackOverflowError
- java.lang.OutOfMemoryError: Java heap space
- java.lang.OutOfMemoryError: GC ovverhead limit exceeded
- java.lang.OutOfMemoryError: Direct bufffer memory
- java.lang.OutOfMemoryError: unable to create new native thread
- java.lang.OutOfMemoryError:Metaspace
1 java.lang.StackOverflowError 栈空间撑爆
方法的加载在栈中,栈管运行,易出现在递归方法中,方法特别多把栈空间撑爆了。
1.1 DEMO-栈溢出
public class StackOverflowErrorDemo {
//栈一般大小是512-1024
public static void main(String[] args) {
stackOverflowError();
}
private static void stackOverflowError() {
stackOverflowError();
}
}
输出
1.2 StackOverflowError是异常还是错误(Error/Exception)
查看虚拟机错误
查看StackOverflowError,是错误级别
组织架构:
2 java.lang.OutOfMemoryError: Java heap space
堆内存不够用了,对象太多了
2.1 DEMO-堆溢出
public class JavaHeapSpaceDemo {
//前提,先把内存调小,-Xms10m -Xmx10m
public static void main(String[] args) {
String str = "test";
while (true) {
str+=str+new Random().nextInt(11111111)+new Random().nextInt(22222222);
str.intern();
}
//或者定义一个超大数组
//byte[] bytes = new byte[80*1024*1024];
}
}
输出
3 java.lang.OutOfMemoryError: GC ovverhead limit exceeded
java内存极具上升,大量对象装载新建,GC超过最高警戒
3.1 DEMO-GC
/**
* User: mxy
* Date: 2021/8/9
* Time: 13:20
* Description: GC过高
* -Xms10m -Xmx10m -XX:+PrintGCDetails -XX:MaxDirectMemorySize=5m
*/
public class GCOverheadDemo {
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;
}
}
}
输出
可以看出
每次GC的时候,前后数值对比没什么变化。GC效果不明显,所以GC overhead
4 java.lang.OutOfMemoryError: Direct bufffer memory
直接内存挂了,这个故障是非常严重的,netty(底层NIO),NIO程序会经常出现。
元空间并不在虚拟机中,而是使用本地内存。
System.out.println("配置的最大直接内存maxDirectMemory:" + (sun.misc.VM.maxDirectMemory()/(double)1024/1024)+"MB");
//输出
配置的maxDirectMemory:3609.0MB
4.1 DEMO-Direct bufffer memory
/**
* User: mxy
* Date: 2021/8/9
* Time: 13:20
* Description: GC过高
* 容易出现在NIO程序
* 未分配在JVM内存中,不属于GC管辖范围,在本地内存中经常建对象,本地内存用光,又不会GC,就会出现错误。
* 本地内存:物理内存JVM外面默认能用的最大内存,未配置时默认1/4。
*
* -Xms10m -Xmx10m -XX:+PrintGCDetails -XX:MaxDirectMemorySize=5m
*/
public class DirectBufferMemoryDemo {
public static void main(String[] args) {
System.out.println("配置的最大直接内存maxDirectMemory:" + (sun.misc.VM.maxDirectMemory()/(double)1024/1024)+"MB");
try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); }
//配置 -XX:MaxDirectMemorySize=5m,使用6m
ByteBuffer bb = ByteBuffer.allocateDirect(6*1024*1024);
}
}
输出
5 java.lang.OutOfMemoryError: unable to create new native thread
不能够创建更多的本地线程
程序部署到生产环境,创建线程的上线已经达到了,高并发经常会遇到。电商,物流,银行系统可能会遇到此故障。
题外话:
Thread t1 = new Thread();
t1.start();
t1.start();
//为什么再次start会报异常:
// 因为底层代码中有threadStatus的控制,threadStatus = 0; 第二次进入threadStatus已改
5.1 DEMO-线程过多(在LINUX运行此程序代码,windows测试的时候要很久)
public class UnableCreateNewThreadDemo {
public static void main(String[] args) {
for (int i = 0; ; i++) {
System.out.println("****i="+i);
new Thread(() -> {
try {
Thread.sleep(Integer.MAX_VALUE);
} catch (InterruptedException e) {
e.printStackTrace();
}
}, ""+i).start();
}
}
}
输出
linux自身可能占用到了一部分,所以 i != 1024.
解决:杀掉进程
5.2 解决方案
5.2.1.非root用户登录linux系统测试
root用户有权限,可以一直new,一般人是非root用户
5.2.2.服务器级别调参调优
6 java.lang.OutOfMemoryError:Metaspace
元空间是方法区,装类的各种元素,常量池之类
初始大小约20M,不停的放类进去,就会满。
6.1 DEMO-Metaspace
输出
7 参考文献
以上内容均来自于下方视频,博客内容仅作为个人学习笔记记录
【1】Java面试_高频重点面试题 (第一、二、三季)_ 面试 第1、2、3季_柴林燕_周阳_哔哩哔哩_bilibili