我是靠谱客的博主 朴素奇异果,这篇文章主要介绍五种OOM异常,现在分享给大家,希望可以做个参考。

目录

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

heap Space OOM

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

复制代码
1
2
3
4
5
6
7
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
复制代码
1
2
3
4
5
6
7
8
9
10
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,那程序就直接崩溃了。

复制代码
1
2
3
4
5
6
7
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
3
1. 你的应用创建了太多线程了,一个应用进程创建太多线程,超过系统承载极限 2. 你的服务器并不允许你的应用程序创建这么多线程,Linux系统默认会允许单个线程可以创建的线程数是1024个

验证代码:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//到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
3
1. 修改服务器配置文件,增加每个线程的进程数 2. 想办法减低应用程序线程的数量

MetaSpace OOM

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

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

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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异常内容请搜索靠谱客的其他文章。

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

评论列表共有 0 条评论

立即
投稿
返回
顶部