Java 常见内存溢出异常与代码实现

Java 堆 OutOfMemoryError

Java 堆是用来存储对象实例的, 因此如果我们不断地创建对象, 并且保证 GC Root 和创建的对象之间有可达路径以免对象被垃圾回收, 那么当创建的对象过多时, 会导致 heap 内存不足, 进而引发 OutOfMemoryError 异常.

public class OutOfMemoryErrorTest{
public static void main (String[] args){
List<Integer> list = new ArryList<>();
int i=0;
while(true){
list.add(i++);
}}}

上面是一个引发 OutOfMemoryError 异常的代码, 我们可以看到, 它就是通过不断地创建对象, 并将对象保存在 list 中防止其被垃圾回收, 因此当对象过多时, 就会使堆内存溢出。

通过 java -Xms10m -Xmx10m -XX:+HeapDumpOnOutOfMemoryError 我们设置了堆内存为 10 兆, 并且使用参数 -XX:+HeapDumpOnOutOfMemoryError 让 JVM 在发生 OutOfMemoryError 异常时打印出当前的内存快照以便于后续分析.

编译运行上述代码后, 会有如下输出:

>>>java -Xms10m - Xms10m-XX:HeapDumpOnOutOfMemoryError com.test.OutOfMemoryErrorTest 16-10-12 10:28
java.lang.OutOfMemoryError:Java heap space
Dumping heap to java_pid1810.hprof...
Heap dump file created [14212861 bytes in 0.128 secs]
Exception in thread "main" java.lang.OutOfMemoryError:Java heap space

at java.util.Arrays.copyof(Arrays.java:3210)

at java.util.Arrays.copyof(Arrays.java:3181)
Java 栈 StackOverflowError

我们知道, JVM 的运行时数据区中有一个叫做 虚拟机栈 的内存区域, 此区域的作用是: 每个方法在执行时都会创建一个栈帧, 用于存储局部变量表, 操作数栈, 方法出口等信息.

因此我们可以创建一个无限递归的递归调用, 当递归深度过大时, 就会耗尽栈空间, 进而导致了 StackOverflowError 异常.

下面是具体的代码:

public class OutOfMemoryErrorTest{
public static void main (String [] srgs){
stackOutOfMemoryError(1);
)

public static void stackOutOfMemoryError(int depth){
depth++;
stackOutOfMemoryError(depth);
}}

当编译运行上述的代码后, 会输出如下异常信息:

Exception in thread "main" java.lang.StackOverflowError
at com.test.OutOfMemoryErrorTest.stackOutOfMemoryError(OutOfMemoryErrorTest.java:27)

文章转载自 乐橙谷http://www.lechenggu.com/bbs/topic/57fda29f9c73a464f54e656e

原文地址:https://www.cnblogs.com/linglipinger/p/5953397.html