对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 class TestHeapMemory {
 7
 8     static class OOMObject{
 9
10     }
11
12     public static void main(String[] args){
13         List<OOMObject> list = new ArrayList<OOMObject>();
14         while (true){
15             list.add(new OOMObject());
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.134 secs]
    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延时),发现堆内存一路上涨,最后崩掉了。

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

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

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

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

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

两种异常:

  • StackOverFlow异常:线程请求的栈深度大于虚拟机允许的最大深度。
  • OutOfMemory异常:虚拟机扩展栈时无法申请到足够的内存空间。

虚拟机参数:

-Xss128k

代码:

 1 /**
 2  * Created by zcy on 2017/6/11.
 3  */
 4 public class TestStackOF {
 5
 6     private static int stackLength = 0;
 7
 8     public static void stackLeak() throws InterruptedException {
 9         stackLength++;
10         stackLeak();
11     }
12
13     public static void main(String args[]) throws Throwable {
14         try{
15             TestStackOF.stackLeak();
16         }
17         catch (Throwable e){
18             System.out.println("stack length is: " + stackLength);
19             throw e;
20         }
21     }
22 }

运行结果:

stack length is: 1102
Exception 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)绝大多数情况下都够用了。有错误堆栈可以阅读。
  • 如果由于建立线程过多导致的内存溢出,可以减少堆容量和每个进程的栈容量换取更多的线程。

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

时间: 2024-10-09 23:28:55

对Java OutOfMemory异常的探究的相关文章

java中异常类与类别

异常类的层次结构: 在 Java 中,所有的异常都有一个共同的祖先 Throwable(可抛出).Throwable 指定代码中可用异常传播机制通过 Java 应用程序传输的任何问题的共性,它们都在java.lang包下面. Error类标记了严重错误,类似内存溢出,虚拟机异常,等等,是不该出现的.这些错误表示故障发生于虚拟机自身.或者发生在虚拟机试图执行应用时,如Java虚拟机运行错误(Virtual MachineError).类定义错误(NoClassDefFoundError)等.这些错

Java基础—异常

一.  Exception异常 1. 概述 异常是程序在运行时出现的错误 异常由来:问题也是现实生活中一个具体的事物,也可以通过java的类的形式进行描述.并封装成对象. 其实就是java对不正常情况进行描述后的对象体现. 2. Java的异常体系 1. 从图中可以看出Throwable下有两个子类,Error和Exception 对于严重的问题,java通过Error类进行描述.对Error类一般不编写针对性的代码对其进行处理. 对于非严重的,java通过Exception类进行描述.对于Ex

Java基础——异常体系

在Java中,异常对象都是派生于Throwable类的一个实例,Java的异常体系如下图所示: 所有的异常都是由Throwable继承而来,在下一层立即分解为两个分支,Error和Exception. Error错误:描述了Java运行时系统的内部错误和资源耗尽错误.一般是指虚拟机相关的问题,如系统崩溃,虚拟机出错误等,这种错误无法恢复或不可能捕获,将导致应用程序中断,通常不处理.因为如果出现这样的内部错误,除了通告用户,并尽力使程序安全地终止之外,再也无能为力了. Exception异常:Ja

java.outOfMemory

http://www.kdgregory.com/index.php?page=java.outOfMemory Java Platform, Standard Edition HotSpot Virtual Machine Garbage Collection Tuning Guide http://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/index.html

Java Exception异常介绍

 一:介绍java异常 异常指不期而至的各种状况,如:文件找不到.网络连接失败.非法参数等.异常是一个事件,它发生在程序运行期间,干扰了正常的指令流程.Java通 过API中Throwable类的众多子类描述各种不同的异常.因而,Java异常都是对象,是Throwable子类的实例,描述了出现在一段编码中的 错误条件.当条件生成时,错误将引发异常. 在 Java 中,所有的异常都有一个共同的祖先 Throwable(可抛出).Throwable 指定代码中可用异常传播机制通过 Java 应用程序

Java socket异常

Java socket异常 分类: Java 2013-07-15 22:38 981人阅读 评论(0) 收藏 举报 目录(?)[+] 使用Java socket编写程序时,通常会遇到几种种异常:BindException.UnknownHostException.ConnectException.SocketTimeoutException. BindException 会发生在Socket或ServerSocket的bind()操作中,如果无法与本机指定的IP地址或端口绑定,就会抛出此异常.

Java基础——异常(2)

throws 和 throw 有什么区别? 1.位置不同:throws用在函数上,后面跟的是异常类,可以跟很多个. throw用在函数内,后面跟的是异常对象. 2.功能不同:throws用来声明异常,让调用者知道功能有可能出现问题,并由调用者可以给出预先的处理方式. throw抛出具体问题对象.执行到throw功能已经结束了,跳转到调用者(谁调用跳哪去),并将具体的问题对象抛给了调用者. 异常体系最大的特点就是体系中的类以及类产生的对象,都具备可抛性.可抛性的意思就是可以被throws和thro

Java并发编程:Java ConcurrentModificationException异常原因和解决方法

Java ConcurrentModificationException异常原因和解决方法 在前面一篇文章中提到,对Vector.ArrayList在迭代的时候如果同时对其进行修改就会抛出java.util.ConcurrentModificationException异常.下面我们就来讨论以下这个异常出现的原因以及解决办法. 以下是本文目录大纲: 一.ConcurrentModificationException异常出现的原因 二.在单线程环境下的解决办法 三.在多线程环境下的解决方法 若有不

《java中异常和错误》

异常和错误的区别. 异常: 在Java中程序的错误主要是语法错误和语义错误,一个程序在编译和运行时出现的错误我们统一称之为异常,它是VM(虚拟机)通知你的一种方式,通过这种方式,VM让你知道,你(开发人员)已经犯了个错误,现在有一个机会来修改它.Java中使用异常类来表示异常,不同的异常类代表了不同的异常.但是在Java中所有的异常都有一个基类,叫做Exception. 错误:它指的是一个合理的应用程序不能截获的严重的问题.大多数都是反常的情况.错误是VM的一个故障(虽然它可以是任何系统级的服务