out of memory java_对Java OutOfMemory异常的探究

Java堆溢出

虚拟机参数:

-Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError

将堆的最小值和最大值都限制成为20M,-XX:+HeapDumpOnOutOfMemoryError出现内存异常时令java虚拟机Dump堆内存转储快照

代码

1 import java.util.*;2

3 /**

4 * Created by zcy on 2017/6/11.5 */

6 public classTestHeapMemory {7

8 static classOOMObject{9

10 }11

12 public static voidmain(String[] args){13 List list = new ArrayList();14 while (true){15 list.add(newOOMObject());16 }17 }18 }

运行出现异常:

java.lang.OutOfMemoryError: Java heap space

Dumping heap to java_pid9392.hprof ...

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)

at java.util.ArrayList.grow(ArrayList.java:261)

at java.util.ArrayList.ensureExplicitCapacity(ArrayList.java:235)

at java.util.ArrayList.ensureCapacityInternal(ArrayList.java:227)

Heap dump file created [28361944 bytes in 0.134secs]

at java.util.ArrayList.add(ArrayList.java:458)

at TestHeapMemory.main(TestHeapMemory.java:15)

为了查看实时堆的使用情况,我们可以安装VisualVM Launcher。

安装请参考http://www.oschina.net/translate/setting-up-visualvm-in-under-5-minutes

使用VisualVM Launcher调试程序(需要在程序中sleep延时),发现堆内存一路上涨,最后崩掉了。

9a41c67ad67d5341caa31fa6f3992a7d.png

查看dump file,绝大多数内存都被数组占用了

4ff866d43e09053192d0628bed5b5a57.png

要解决Heap的OutOfMemory,一般的手段是使用内存映像分析工具,分析堆转储文件,重点是确认内存中的对象是否是必要的,也就是要先分清楚到底是出现了内存泄露还是内存溢出。

如果是内存泄露,可以进一步使用工具查看到GC Roots的引用链。于是就能找到泄露对象是通过怎样的路径与GC Roots相关联,导致GC无法自动回收。

如果每个对象都有必要存活着,那么应该检查堆参数(-Xms和-Xmx)是否还可以调大

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

两种异常:

StackOverFlow异常:线程请求的栈深度大于虚拟机允许的最大深度。

OutOfMemory异常:虚拟机扩展栈时无法申请到足够的内存空间。

虚拟机参数:

-Xss128k

代码:

1 /**

2 * Created by zcy on 2017/6/11.3 */

4 public classTestStackOF {5

6 private static int stackLength = 0;7

8 public static void stackLeak() throwsInterruptedException {9 stackLength++;10 stackLeak();11 }12

13 public static void main(String args[]) throwsThrowable {14 try{15 TestStackOF.stackLeak();16 }17 catch(Throwable e){18 System.out.println("stack length is: " +stackLength);19 throwe;20 }21 }

22 }

运行结果:

stack length is: 1102Exception in thread"main"java.lang.StackOverflowError

at TestStackOF.stackLeak(TestStackOF.java:9)

at TestStackOF.stackLeak(TestStackOF.java:10)

at TestStackOF.stackLeak(TestStackOF.java:10)

at TestStackOF.stackLeak(TestStackOF.java:10)

...

最后总结一下:

对于StackOverFlow异常:栈深度(1000-2000)绝大多数情况下都够用了。有错误堆栈可以阅读。

如果由于建立线程过多导致的内存溢出,可以减少堆容量和每个进程的栈容量换取更多的线程。

方法区和运行时常量池溢出

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值