OOM分好多种,本文就结合代码demo做个总结,既方便自己温故知新,又能和xdm一起学习进步
1. 栈oom
/**
* @description: java.lang.StackOverflowError
* -Xss512K 设置栈空间大小 一般512K到1024K
* Exception in thread "main" java.lang.StackOverflowError
* 就是递归调用的时候没有找到出口,导致栈的空间被撑爆了,一般我们设置栈的空间,一般512K到1024K
* @author: Ding Yawu
* @create: 2022/4/17 3:22 PM
*/
public class StackOverflowerrorDemo {
public static void main(String[] args) {
StackOverflowError();
}
public static void StackOverflowError(){
StackOverflowError();
}
}
注意这是个错误
2. 堆oom
/**
* @description: java.lang.OutOfMemoryError: Java heap space
* 直接new一个大对象,或者不停地创建对象,设置一下-Xms10M -Xmx10M
* @author: Ding Yawu
* @create: 2022/4/17 3:27 PM
*/
public class JavaHeapSpaceDemo {
public static void main(String[] args) {
String str = "roy";
/*while (true){
str += new Random().nextInt(1111111) + new Random().nextInt(222222);
str.intern();
}*/
byte[] bytes = new byte[1024 * 1024 * 10 ];

}
}
3. GC超过限制导致OOM
/**
* @description: java.lang.OutOfMemoryError: GC overhead limit exceeded
* 超过98%的时间用来GC了并且回收不到2%的堆内存
-Xms5M -Xmx5M -XX:+PrintGCDetails -XX:MaxDirectMemorySize=5M
*
* @author: Ding Yawu
* @create: 2022/4/17 3:39 PM
*/
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();
}
}
}
4. 直接内存OOM
/**
* @description: java.lang.OutOfMemoryError: Direct buffer memory
* -Xms10m -Xmx10m -XX:+PrintGCDetails -XX:MaxDirectMemorySize=5m
* 元空间本质上和永久代相似,都是JVM方法区概念的具体实现,区别在与元空间不在虚拟机中,而是使用本地内存,所以元空间不指定大小就是受本地内存限制
* @author: Ding Yawu
* @create: 2022/4/17 4:04 PM
*/
public class DirectBufferMemoryDemo {
public static void main(String[] args) {
System.out.println("配置的maxDirectMemory:" + VM.maxDirectMemory()/1024 / 1024 + "MB");
try {
Thread.sleep(2000);
}catch(Exception e){
e.printStackTrace();
}
//分配在操作系统的本地内存,不属于GC的管辖
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(6 * 1024 * 1024);
}
}
5. 元空间 OOM
/**
* @description: java.lang.OutOfMemoryError: Metaspace
* -XX:MetaspaceSize=8m
* @author: Ding Yawu
* @create: 2022/4/17 5:26 PM
*/
public class metaSpaceOOMTest {
public static void main(String[] args) {
int i = 0;
while (true){
try {
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 =" + i);
e.printStackTrace();
}
}
}
static class OOMTest{
}
}
6. 线程过多导致OOM
/**
* java.lang.OutOfMemoryError:unbale to create new native thread
*
* 高并发请求服务器时,经常出现如下异常:java.lang.OutOfMemoryError:unbale to create new native thread
* 准确的讲该native thread异常与对应的平台有关。
*
* 导致原因:
* 应用创建了太多线程,一个应用进程创建多个线程,超过系统承载极限。
* 服务器并不允许应用程序创建那么多线程,linux系统默认允许单个进程可以创建的线程数是1024个,如果应用创建超过这个数量,就会报java.lang.OutOfMemoryError:unable to create new native thread
*
* 解决办法:
* 想办法降低应用程序创建线程的数量,分析应用是否真的需要创建那么多线程,如果不是,改代码将线程数降到最低。
* 对于有的应用,确实需要创建多个线程,远超过linux系统默认的1024个线程的限制,可以通过修改linux服务器配置,扩大linux默认限制。
*/
public class UnableCreateNewThreadDemo {
public static void main(String[] args) {
for (int i=1; ;i++){
System.out.println("******************* i = " +i);
new Thread(()->{
try {
TimeUnit.SECONDS.sleep(Integer.MAX_VALUE);
} catch (InterruptedException e) {
e.printStackTrace();
}
},""+i).start();
}
}
}
6.1 linux 下的操作
linux下操作 javac -d . UnableCreateNewThreadDemo.java java UnableCreateNewThreadDemo
退不出来了
登录另外一个客户端 kill -9 pid
6.2 一个进程可以创建多少个线程
可以执行 ulimit -a 这条命令,查看进程创建线程时默认分配的栈空间大小,比如我这台服务器默认分配给线程的栈空间大小为 8M。
可以修改的 ulimit -s 512
这个目录下可以限制一个用户下的创建线程的数量的限制
top命令可以查看线程的数量
我参考的这篇文章:blog.csdn.net/qq_34827674…
我参考的OOM视频 www.bilibili.com/video/BV1Eq…