目录
- 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
7public 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参数会生产这种异常:
- -Xmx10m
- -Xms10m
- -XX:+PrintGCDetails
- -XX:MaxDirectMemorySize=3m
复制代码
1
2
3
4
5
6
7
8
9
10public 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
7public 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
31. 你的应用创建了太多线程了,一个应用进程创建太多线程,超过系统承载极限 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
31. 修改服务器配置文件,增加每个线程的进程数 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
23static 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异常内容请搜索靠谱客的其他文章。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复