我是靠谱客的博主 朴素奇异果,最近开发中收集的这篇文章主要介绍五种OOM异常,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

目录

    • heap Space OOM
    • GC overhead limit OOM
    • Direct buffer memory OOM
    • UnableToCreateNewNativeThread OOM
    • MetaSpace OOM

heap Space OOM

这种异常经常出现,通常都会出现这个异常,表示内存空间不够,使用如下代码,用一个死循环来生产字符串,由于Java8之后字符串常量池放在堆里面,就会报这个异常

public static void main(String[] args) {
String str = "aaaa";
while (true){
str += str + new Random().nextInt(); //Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
}
}

GC overhead limit OOM

这种情况一般指GC线程运行的时间远大于用户线程的时间,比如说GC占了98%的CPU,用户线程只占了2%

设置如下JVM参数会生产这种异常:

  1. -Xmx10m
  2. -Xms10m
  3. -XX:+PrintGCDetails
  4. -XX:MaxDirectMemorySize=3m
public static void main(String[] args) {
//Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded
//超过98%的时间来进行GC并且回收了不到2%的堆内存
int i = 0;
List<String> list = new ArrayList<>();
while (true){
list.add(String.valueOf(++i).intern());
}
}

Direct buffer memory OOM

一般在做nio异常的时候会出现

ps: ByteBuffer.allocate(capability) 第一种方式是分配JVM堆内存,属于GC管辖范围,由于需要拷贝所以速度相对较慢。 DirectByteBuffer dires = ByteBuffer.allocateDirect(capability),第二种方式是分配OS本地内存,不属于GC管辖范围,由于不需要内存拷贝所以速度相对较快。

DirectByteBuff 对象作为这块内存的引用进行操作,但如果不断分配本地内存,堆内存很少使用,那么JVM就不需要执行GC,DirectByteBuffer对象们就不会被回收,这时候堆内存充足,但本地内存已经使用光了,再次尝试分配本地内存就会出现OutOfMemoryError,那程序就直接崩溃了。

public static void main(String[] args) {
System.out.println(VM.maxDirectMemory()+" MaxDirectMemory内存");
//一般再做NIO异常的时候会出现
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(6 * 1024 * 1024);
//Exception in thread "main" java.lang.OutOfMemoryError: Direct buffer memory
}

UnableToCreateNewNativeThread OOM

导致原因:

1. 你的应用创建了太多线程了,一个应用进程创建太多线程,超过系统承载极限
2. 你的服务器并不允许你的应用程序创建这么多线程,Linux系统默认会允许单个线程可以创建的线程数是1024个

验证代码:

 //到Linux主机上运行哈
public static void main(String[] args) {
for (int i = 0;; i++) {
System.out.println("i= "+i);
new Thread( () -> {
System.out.println("i'm creating");
try {
TimeUnit.SECONDS.sleep(Integer.MAX_VALUE);
} catch (InterruptedException e) {
e.printStackTrace();
}
},String.valueOf(i)).start();
}
}

解决方案:

1. 修改服务器配置文件,增加每个线程的进程数
2. 想办法减低应用程序线程的数量

MetaSpace OOM

简单来说,就是元空间的内容太多,元空间的内存不足

设置参数: -XX:MetaSpaceSize=8m -XX:MaxMetaSpaceSize=8m

static class OOMTest{
}
public static void main(final String[] args) {
int i = 0;//模拟计数多少次后发生异常
try {
while (true){
i++;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(OOMTest.class);
enhancer.setUseCache(false);
enhancer.setCallback(new MethodInterceptor() {
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
return methodProxy.invokeSuper(o,args);
}
});
enhancer.create();
}
}catch (Exception e){
System.out.println("第多少次发生异常: "+i);
e.printStackTrace();
}
}

最后

以上就是朴素奇异果为你收集整理的五种OOM异常的全部内容,希望文章能够帮你解决五种OOM异常所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(56)

评论列表共有 0 条评论

立即
投稿
返回
顶部