Java虚拟机OutOfMemoryError 异常详解及解决方法(3)

这里写图片描述

上图是一张Java运行时的内存分布图,可知虚拟机内存都有发生OutOfMemoryError(下文称 OOM)异常的可能,作为一个合格的Java开发人员,我们应该做到的是:

(1)第一,通过代码验证 Java 虚拟机规范中描述的各个运行时区域储存的内容;
(2)第二,遇到内存溢出的时候,应该可以找打具体的位置,并进行合理的解决;

下边就聊一下 OOM:

一、Java 堆溢出

我们知道Java 堆用于储存对象实例,我们只要不断地创建对象,并且保证 GC Roots 到对象之间有可达路径来避免垃圾回收机制清除这些对象,就会在对象数量到达最大堆的容量限制后产生内存溢出异常(OOM)。

案例如下:

/**
 * VM Args: -Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError
 * 需要在jre1.5下编译
 * @author xuliugen
 */
public class HeapOOM {
    static class OOMObject{}
    public static void main(String[] args){
        List<OOMObject> list = new ArrayList<OOMObject>();
        while(true){
            list.add(new OOMObject());
        }
    }
}

为了能够看到内存溢出时候的状态信息,在项目右键–run as –run configuration –Arguments

这里写图片描述

然后可以看到爆出一下错误:

java.lang.OutOfMemoryError: Java heap space
Dumping heap to java_pid6424.hprof ...
Heap dump file created [28129384 bytes in 0.118 secs]
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at java.util.Arrays.copyOf(Unknown Source)
    at java.util.Arrays.copyOf(Unknown Source)
    at java.util.ArrayList.grow(Unknown Source)
    at java.util.ArrayList.ensureExplicitCapacity(Unknown Source)
    at java.util.ArrayList.ensureCapacityInternal(Unknown Source)
    at java.util.ArrayList.add(Unknown Source)
    at com.lc.oom.HeapOOM.main(HeapOOM.java:21)

Java 堆内存的 OOM 异常是实际应用中最常见的内存溢出异常情况。出现 Java 堆内存溢出时,异常堆栈信息“java.lang.OutOfMemoryError”会跟着进一步提示“Java heap space”。要解决这个区域的异常,一般的方法是首先通过内存映像分析工具(如 Eclipse Memory Analyzer)对 dump 出来的堆转储快照进行分析,重点是确认内存中的对象是否是必要的,也就是要先分清楚到底是出现了内存泄漏( Memory Leak)还是内存溢出( Memory Overflow)。可以使用 EclipseMemory Analyzer 打开的堆转储快照文件。( Eclipse Memory Analyzer是一个eclipse插件,网上百度一下,很多)

如果是内存泄漏,可进一步通过工具查看泄漏对象到 GC Roots 的引用链。于是就能找到泄漏对象是通过怎样的路径与 GC Roots 相关联并导致垃圾收集器无法自动回收它们的。握了泄漏对象的类型信息,以及 GC Roots 引用链的信息,就可以比较准确地定位出泄漏代码的位置。

如果不存在泄漏,换句话说就是内存中的对象确实都还必须存活着,那就应当检查虚拟机的堆参数( -Xmx 与-Xms),与机器物理内存对比看是否还可以调大,从代码上检查是否存在某些对象生命周期过长、持有状态时间过长的情况,尝试减少程序运行期的内存消耗。

以上是处理 Java 堆内存问题的简略思路。

下一篇,讲学习一下 : 虚拟机栈和本地方法栈溢出

发布了508 篇原创文章 · 获赞 3628 · 访问量 512万+
展开阅读全文

java.lang.OutOfMemory异常

11-24

各位大神,小生在做excel导出的时候遇见了这么一个问题,作为实习生实在是莫名其妙,求各位大神帮个小忙。 java.lang.OutOfMemoryError: GC overhead limit exceeded 16:31:22.700 [nioEventLoopGroup-2-8] WARN io.netty.channel.nio.NioEventLoop - Unexpected exception in the selector loop. java.lang.OutOfMemoryError: GC overhead limit exceeded at java.util.ArrayList.iterator(ArrayList.java:814) ~[na:1.7.0_80] at sun.nio.ch.WindowsSelectorImpl.updateSelectedKeys(WindowsSelectorImpl.java:496) ~[na:1.7.0_80] at sun.nio.ch.WindowsSelectorImpl.doSelect(WindowsSelectorImpl.java:172) ~[na:1.7.0_80] at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:87) ~[na:1.7.0_80] at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:98) ~[na:1.7.0_80] at io.netty.channel.nio.NioEventLoop.select(NioEventLoop.java:622) ~[netty-transport-4.0.32.Final.jar:4.0.32.Final] at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:310) ~[netty-transport-4.0.32.Final.jar:4.0.32.Final] at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:112) [netty-common-4.0.32.Final.jar:4.0.32.Final] at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:137) [netty-common-4.0.32.Final.jar:4.0.32.Final] at java.lang.Thread.run(Thread.java:745) [na:1.7.0_80] 16:31:23.334 [Thread-6] ERROR o.a.e.i.a.AcquireTimerJobsRunnable - exception during timer job acquisition: GC overhead limit exceeded java.lang.OutOfMemoryError: GC overhead limit exceeded at java.util.Arrays.copyOf(Arrays.java:2367) ~[na:1.7.0_80] at java.lang.AbstractStringBuilder.expandCapacity(AbstractStringBuilder.java:130) ~[na:1.7.0_80] at java.lang.AbstractStringBuilder.ensureCapacityInternal(AbstractStringBuilder.java:114) ~[na:1.7.0_80] at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:415) ~[na:1.7.0_80] at java.lang.StringBuilder.append(StringBuilder.java:132) ~[na:1.7.0_80] at org.apache.ibatis.reflection.wrapper.BeanWrapper.getBeanProperty(BeanWrapper.java:171) ~[mybatis-3.3.0.jar:3.3.0] at org.apache.ibatis.reflection.wrapper.BeanWrapper.get(BeanWrapper.java:49) ~[mybatis-3.3.0.jar:3.3.0] at org.apache.ibatis.reflection.MetaObject.getValue(MetaObject.java:122) ~[mybatis-3.3.0.jar:3.3.0] at org.apache.ibatis.executor.BaseExecutor.createCacheKey(BaseExecutor.java:212) ~[mybatis-3.3.0.jar:3.3.0] at org.apache.ibatis.executor.CachingExecutor.createCacheKey(CachingExecutor.java:139) ~[mybatis-3.3.0.jar:3.3.0] at org.apache.ibatis.executor.CachingExecutor.query(CachingExecutor.java:81) ~[mybatis-3.3.0.jar:3.3.0] at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:120) ~[mybatis-3.3.0.jar:3.3.0] at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:113) ~[mybatis-3.3.0.jar:3.3.0] at org.activiti.engine.impl.db.DbSqlSession.selectListWithRawParameter(DbSqlSession.java:438) ~[activiti-engine-5.19.0.2.jar:5.19.0.2] at org.activiti.engine.impl.db.DbSqlSession.selectList(DbSqlSession.java:429) ~[activiti-engine-5.19.0.2.jar:5.19.0.2] at org.activiti.engine.impl.db.DbSqlSession.selectList(DbSqlSession.java:424) ~[activiti-engine-5.19.0.2.jar:5.19.0.2] at org.activiti.engine.impl.db.DbSqlSession.selectList(DbSqlSession.java:411) ~[activiti-engine-5.19.0.2.jar:5.19.0.2] at org.activiti.engine.impl.persistence.entity.JobEntityManager.findNextTimerJobsToExecute(JobEntityManager.java:157) ~[activiti-engine-5.19.0.2.jar:5.19.0.2] at org.activiti.engine.impl.cmd.AcquireTimerJobsCmd.execute(AcquireTimerJobsCmd.java:45) ~[activiti-engine-5.19.0.2.jar:5.19.0.2] at org.activiti.engine.impl.cmd.AcquireTimerJobsCmd.execute(AcquireTimerJobsCmd.java:29) ~[activiti-engine-5.19.0.2.jar:5.19.0.2] at org.activiti.engine.impl.interceptor.CommandInvoker.execute(CommandInvoker.java:24) ~[activiti-engine-5.19.0.2.jar:5.19.0.2] at org.activiti.engine.impl.interceptor.CommandContextInterceptor.execute(CommandContextInterceptor.java:57) ~[activiti-engine-5.19.0.2.jar:5.19.0.2] at org.activiti.spring.SpringTransactionInterceptor$1.doInTransaction(SpringTransactionInterceptor.java:47) ~[activiti-spring-5.19.0.2.jar:5.19.0.2] at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:133) ~[spring-tx-4.2.2.RELEASE.jar:4.2.2.RELEASE] at org.activiti.spring.SpringTransactionInterceptor.execute(SpringTransactionInterceptor.java:45) ~[activiti-spring-5.19.0.2.jar:5.19.0.2] at org.activiti.engine.impl.interceptor.LogInterceptor.execute(LogInterceptor.java:31) ~[activiti-engine-5.19.0.2.jar:5.19.0.2] at org.activiti.engine.impl.cfg.CommandExecutorImpl.execute(CommandExecutorImpl.java:40) ~[activiti-engine-5.19.0.2.jar:5.19.0.2] at org.activiti.engine.impl.cfg.CommandExecutorImpl.execute(CommandExecutorImpl.java:35) ~[activiti-engine-5.19.0.2.jar:5.19.0.2] at org.activiti.engine.impl.asyncexecutor.AcquireTimerJobsRunnable.run(AcquireTimerJobsRunnable.java:52) ~[activiti-engine-5.19.0.2.jar:5.19.0.2] at java.lang.Thread.run(Thread.java:745) [na:1.7.0_80] /report/collectionPaymentClass-report-down java.lang.OutOfMemoryError: GC overhead limit exceeded 问答

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 编程工作室 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览