内容简介:“Shallow Heap”:类本身元数据的大小。“Retained Heap”:该类以及它引用的其他类所占用空间的总和
Java虚拟机中哪些区域会发生OOM
堆、虚拟机栈、本地方法栈、方法区、直接内存
堆OOM
测试程序:
/** * VM Args: -Xms10m -Xmx10m -XX:+HeapDumpOnOutOfMemoryError * User:wangs * Date:2018/8/23 */ public class HeapOOM { public static void main(String[] args) { List<Object> list = new ArrayList<>(); while (true) { list.add(new Object()); } } } 复制代码
运行结果:
java.lang.OutOfMemoryError: Java heap space Dumping heap to java_pid18148.hprof ... Exception in thread "main" java.lang.OutOfMemoryError: Java heap space Heap dump file created [13355339 bytes in 0.137 secs] at java.util.Arrays.copyOf(Arrays.java:3210) at java.util.Arrays.copyOf(Arrays.java:3181) at java.util.ArrayList.grow(ArrayList.java:261) at java.util.ArrayList.ensureExplicitCapacity(ArrayList.java:235) at java.util.ArrayList.ensureCapacityInternal(ArrayList.java:227) at java.util.ArrayList.add(ArrayList.java:458) at com.thinkinjava.jvm.HeapOOM.main(HeapOOM.java:18) 复制代码
用MAT工具打开堆快照文件:
“Shallow Heap”:类本身元数据的大小。“Retained Heap”:该类以及它引用的其他类所占用空间的总和
大概的分析步骤就是这样,关于MAT的使用,可以去多了解下。
栈OOM
- 线程请求的栈深度大于虚拟机所允许的最大深度,将抛出StackOverflowError。
- 如果虚拟机在扩展栈时无法申请到足够的内存,则抛出OOM。
测试程序:
/** * VM Args:-Xss128k * User:wangs * Date:2018/8/27 */ public class StackOOM { private int stackLength = 1; public static void main(String[] args) { StackOOM stackOOM = new StackOOM(); try { stackOOM.test(); } catch (Throwable e) { System.out.println("stack length:" + stackOOM.stackLength); throw e; } } private void test() { stackLength++; test(); } } 复制代码
运行结果:
stack length:994 Exception in thread "main" java.lang.StackOverflowError at com.thinkinjava.jvm.StackOOM.test(StackOOM.java:25) at com.thinkinjava.jvm.StackOOM.test(StackOOM.java:26) at com.thinkinjava.jvm.StackOOM.test(StackOOM.java:26) at com.thinkinjava.jvm.StackOOM.test(StackOOM.java:26) at com.thinkinjava.jvm.StackOOM.test(StackOOM.java:26) at com.thinkinjava.jvm.StackOOM.test(StackOOM.java:26) at com.thinkinjava.jvm.StackOOM.test(StackOOM.java:26) at com.thinkinjava.jvm.StackOOM.test(StackOOM.java:26) at com.thinkinjava.jvm.StackOOM.test(StackOOM.java:26) at com.thinkinjava.jvm.StackOOM.test(StackOOM.java:26) at com.thinkinjava.jvm.StackOOM.test(StackOOM.java:26) at com.thinkinjava.jvm.StackOOM.test(StackOOM.java:26) at com.thinkinjava.jvm.StackOOM.test(StackOOM.java:26) at com.thinkinjava.jvm.StackOOM.test(StackOOM.java:26) 复制代码
上篇文章 深入理解Java虚拟机之栈帧 ,介绍了栈帧,我们来回顾一下:栈帧是保存在虚拟机栈中的,栈帧是用来存储数据和存储部分过程结果的数据结构,同时也被用来处理动态链接(Dynamic Linking)、方法返回值和异常分派(Dispatch Exception)。栈帧越大,栈深度越小。方法参数过多或者局部变量过多都会使栈深度变小,如果超过-xss设置的栈内存容量,就会导致栈溢出。
方法区OOM
测试程序:
/* * VM Args: -XX:PermSize=10m -XX:MaxPermSize=10m */ public class RuntimeConstantPoolOOM { public static void main(String[] args) { List<String> list = new ArrayList<>(); int i = 0; while (true) { list.add(String.valueOf(i++).intern()); } } } 复制代码
在JDK1.6及之前版本中,由于常量池分配在永久代中(即方法区),我们可以通过-XX:PermSize和-XX:MaxPermSize限制方法区大小,从而间接限制其中常量池的容量。运行时常量池溢出: java.lang.OutOfMemoryError: PermGen space
。
JDK1.7常量池不在存储对象,而是存储对象的引用。修改虚拟机参数 -Xms10m -Xmx10m -XX:+HeapDumpOnOutOfMemoryError
,运行结果如下:
Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded at java.lang.Integer.toString(Integer.java:401) at java.lang.String.valueOf(String.java:3099) at com.thinkinjava.jvm.RuntimeConstantPoolOOM.main(RuntimeConstantPoolOOM.java:14) 复制代码
异常的意思是程序花在垃圾回收上的时间太多,却没有什么效果。默认的话,如果98%的时间都花在GC上并且回收了才不到2%的空间的话,虚拟机就会抛这个异常。
JDK1.8移除了永久代,类的元数据信息存储在元空间。元空间并不在虚拟机中,而是使用本地内存。因此,默认情况下,元空间的大小仅受本地内存限制,但可以通过 -XX:MetaspaceSize -XX:MaxMetaspaceSize
参数来指定元空间的大小。
测试程序:
/** * VM Args:-XX:MaxMetaspaceSize=10m * User:wangs * Date:2018/8/27 */ public class MetaspaceOOM { static ClassPool classPool = ClassPool.getDefault(); public static void main(String[] args) throws Exception { int i = 1; while (true){ classPool.makeClass("com.thinkinjava.jvm" + i++).toClass(); } } } 复制代码
运行结果:
Exception in thread "main" java.lang.OutOfMemoryError: Metaspace at javassist.ClassPool.toClass(ClassPool.java:1170) at javassist.ClassPool.toClass(ClassPool.java:1113) at javassist.ClassPool.toClass(ClassPool.java:1071) at javassist.CtClass.toClass(CtClass.java:1264) at com.thinkinjava.jvm.Metaspace.main(Metaspace.java:16) 复制代码
直接内存OOM
测试程序:
/** * VM Args:-Xmx20M -XX:MaxDirectMemorySize=10M * User:wangs * Date:2018/8/27 */ public class DirectMemoryOOM { private static final int _1MB = 1024 * 1024; public static void main(String[] args) throws Exception { Field unsafeField = Unsafe.class.getDeclaredFields()[0]; unsafeField.setAccessible(true); Unsafe unsafe = (Unsafe) unsafeField.get(null); while (true) { unsafe.allocateMemory(_1MB); } } } 复制代码
运行结果:
Exception in thread "main" java.lang.OutOfMemoryError at sun.misc.Unsafe.allocateMemory(Native Method) at com.thinkinjava.jvm.DirectMemoryOOM.main(DirectMemoryOOM.java:21)复制代码
如果读完觉得有收获的话,欢迎点赞、关注、加公众号【Java在线】,查阅更多精彩历史!!!
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 深入dubbo笔记——项目实战
- ItemDecoration深入解析与实战(一)
- ItemDecoration深入解析与实战(二)—— 实际运用
- ItemDecoration深入解析与实战(一)——源码分析
- 深入了解Json Web Token之实战篇
- Hive SQL 综合应用案例实战及多项性能指标深入讲解-DW商业环境实战
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
神经网络在应用科学和工程中的应用
萨马拉辛荷 / 2010-1 / 88.00元
《神经网络在应用科学与工程中的应用:从基本原理到复杂的模式识别》为读者提供了神经网络方面简单但却系统的介绍。 《神经网络在应用科学和工程中的应用从基本原理到复杂的模式识别》以神经网络在科学数据分析中所扮演角色的介绍性讨论作为开始,给出了神经网络的基本概念。《神经网络在应用科学和工程中的应用从基本原理到复杂的模式识别》首先对用于实际数据分析的神经网络结构进行了综合概述,继而对线性网络进行了大量......一起来看看 《神经网络在应用科学和工程中的应用》 这本书的介绍吧!