OutOfMemory模拟(一)

来源:互联网 发布:天津包子馅儿 知乎 编辑:程序博客网 时间:2024/06/05 22:44

在java程序中总会时不时出现一下OOM的异常,来了解一下具体的相应的异常。


首先得做一些准备工作,比如,如何在eclipse中设置java运行的一些参数:




一、JAVA堆溢出


package outOfMemory;import java.util.ArrayList;import java.util.List;/** * @author lu * */public class Test_OutOfMemory {static class OOMObject{}public static void main(String[] args) {List<OOMObject> list = new ArrayList<OOMObject>();while (true){list.add(new OOMObject());System.out.println("增加一个对象成功!");}}}

运行结果是:


[Full GC (Ergonomics) [PSYoungGen: 7734K->7422K(9216K)] [ParOldGen: 8668K->8668K(10240K)] 16403K->16091K(19456K), [Metaspace: 2659K->2659K(1056768K)], 0.0904742 secs] [Times: user=0.21 sys=0.00, real=0.09 secs] 

[Full GC (Allocation Failure) [PSYoungGen: 7422K->7422K(9216K)] [ParOldGen: 8668K->8668K(10240K)] 16091K->16091K(19456K), [Metaspace: 2659K->2659K(1056768K)], 0.0763153 secs] [Times: user=0.25 sys=0.01, real=0.08 secs] 

Exception in thread "main" Heap

 PSYoungGen      total 9216K, used 7606K [0x00000007bf600000, 0x00000007c0000000, 0x00000007c0000000)

  eden space 8192K, 92% used [0x00000007bf600000,0x00000007bfd6dbb8,0x00000007bfe00000)

  from space 1024K, 0% used [0x00000007bff00000,0x00000007bff00000,0x00000007c0000000)

  to   space 1024K, 0% used [0x00000007bfe00000,0x00000007bfe00000,0x00000007bff00000)

 ParOldGen       total 10240K, used 8668K [0x00000007bec00000, 0x00000007bf600000, 0x00000007bf600000)

  object space 10240K, 84% used [0x00000007bec00000,0x00000007bf477390,0x00000007bf600000)

 Metaspace       used 2689K, capacity 4486K, committed 4864K, reserved 1056768K

  class space    used 290K, capacity 386K, committed 512K, reserved 1048576K

java.lang.OutOfMemoryError: Java heap space

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 outOfMemory.Test_OutOfMemory.main(Test_OutOfMemory.java:19)



二、虚拟机栈和本地方法栈溢出

在虚拟机栈和本地方法栈中可能跑出的异常有StackOverflowError(如果县城请求的栈深度大于虚拟机所允许的最大深度)和OutOfMemoryError(如果虚拟机在扩展栈的时候无法申请到足够的内存空间)两种。

其实在这些地方,存在一些重叠的地方:比如:当栈空间无法继续分配的时候,到底是到达了虚拟机允许的最大深度,还是内存太少了?

有两种测试方法:

1、使用-Xss参数减少栈内存的容量。结果:抛出StackOverflowError异常,异常出现时,输出的对栈深度相应减少(因为-Xss减少了)(下面例子验证了。)

2、定义了大量的本地变量,增加此方法帧中本地变量表的长度。结果:抛出stackOverflowError异常时输出的对栈深度相应缩小。

/** * @author lu * VM Args: -Xss 128k * */public class Test_StackOOM {private int stackLength = 1;public void stackLeak(){stackLength++;stackLeak();}public static void main(String[] args) throws Throwable{Test_StackOOM oom = new Test_StackOOM();try{oom.stackLeak();}catch(Throwable e){System.out.println("stack length:"+oom.stackLength);throw e;}}}

运行结果:

stack length:1933

Exception in thread "main" java.lang.StackOverflowError

at outOfMemory.Test_StackOOM.stackLeak(Test_StackOOM.java:14)

at outOfMemory.Test_StackOOM.stackLeak(Test_StackOOM.java:14)

at outOfMemory.Test_StackOOM.stackLeak(Test_StackOOM.java:14)

at outOfMemory.Test_StackOOM.stackLeak(Test_StackOOM.java:14)

at outOfMemory.Test_StackOOM.stackLeak(Test_StackOOM.java:14)

at outOfMemory.Test_StackOOM.stackLeak(Test_StackOOM.java:14)


但是在多线程的结果下:




package outOfMemory;/** * @author lu * 多线程创建线程导致内存溢出异常 * VM Args : -Xss2M */public class Test_StackOOM_2 {private void dontStop(){while(true){}}public void stackLeakByThread(){while(true){Thread thread =new Thread(new Runnable(){publicvoid run(){dontStop();}});thread.start();}}public staticvoid main(String[] args) throws Throwable {Test_StackOOM_2 oom =new Test_StackOOM_2();oom.stackLeakByThread();}}

则会在不久的将来抛出如下异常:

Exception in thread "main" java.lang.OutOfMemoryError: unable to create new native thread

at java.lang.Thread.start0(Native Method)

at java.lang.Thread.start(Thread.java:714)

at outOfMemory.Test_StackOOM_2.stackLeakByThread(Test_StackOOM_2.java:21)

at outOfMemory.Test_StackOOM_2.main(Test_StackOOM_2.java:27)




原创粉丝点击