Java内存溢出和内存泄露后怎么解决

Wesley13
• 阅读 713

1.首先这里先说一下内存溢出和内存泄露的区别:

内存溢出 out of memory,是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory;比如申请了一个integer,但给它存了long才能存下的数,那就是内存溢出。

内存泄露 memory leak,是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光。

memory leak会最终会导致out of memory!

2.我们这里做一个内存溢出的例子

/**
 * VM Args:-Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError
 * @author Administrator
 *
 */

public class TestDump {

    static class OOB {

    }

    public static void main(String[] args) {
        List<OOB> list = new ArrayList<OOB>();
        while (true) {
            list.add(new OOB());
        }
    }

}

其中-Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError是需要加的JVM启动参数

-Xms20m将堆的最小值设置为20MB,-Xmx20m将堆的最大值设置为20MB,当设置一样时即可避免堆自动扩展。

-XX:+HeapDumpOnOutOfMemoryError可以让虚拟机在内存溢出时Dump当前的内存堆转储快照以便事后进行分析。

运行结果:

java.lang.OutOfMemoryError: Java heap space
Dumping heap to java_pid6256.hprof ...
Heap dump file created [27904625 bytes in 0.098 secs]
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at java.util.Arrays.copyOf(Arrays.java:2245)
    at java.util.Arrays.copyOf(Arrays.java:2219)
    at java.util.ArrayList.grow(ArrayList.java:242)
    at java.util.ArrayList.ensureExplicitCapacity(ArrayList.java:216)
    at java.util.ArrayList.ensureCapacityInternal(ArrayList.java:208)
    at java.util.ArrayList.add(ArrayList.java:440)
    at com.webservie.TestDump.main(TestDump.java:18)

异常信息java.lang.OutOfMemoryError: Java heap space。解决该区域问题,一般先通过内存印象分析工具(如Eclipse Memory Analyzer)对Dump出来的堆转储快照进行分析,重点是确认内存中的对象是否是必要的,

要就是先要分清楚到底是出现了内存泄露还是内存溢出。

java_pid6256.hprof就是生成的快照,可以在类所在的工程根目录下找到。

打开该快照文件,如图所示:

Java内存溢出和内存泄露后怎么解决

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

掌握了泄露对象的类型信息及GC Roots引用链的信息,就可以比较准确的定位出泄露代码的位置。

如果不存在泄露,就是内存中的对象确实都还必须存活着,就应该检测虚拟机的堆参数(-Xmx和-Xms),与机器物理内存对比,看看是否可以调大,从代码上检查是否存在某些

对象生命周期过长、持有状态时间过长的情况,尝试减少程序运行期的内存消耗。

点赞
收藏
评论区
推荐文章
待兔 待兔
4个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Wesley13 Wesley13
3年前
java虚拟机(四)
 学习了java运行时数据区,知道每个内存区域保存什么数据,可以参考:https://www.cnblogs.com/huigelaile/p/diamondshine.html,然后了解内存溢出和内存泄露是很有必要的,一方面是为了面试,更重要是的在工作中能够快速定位错误原因并且解决内存溢出分类:1、java.lang.OutOf
九路 九路
3年前
1 Java内存区域与内存溢出异常
1java虚拟机对内存的管理java虚拟机在执行java程序的时候把内存分为若干个不同的区,这些区各自有不同的用处,以及创建和销毁时间.有的区随着虚拟机的启动而启动,有的区则依赖用户线程的启动和结束而启动和结束.根据java虚拟机规范,java虚拟机将内存分为下面几个部分:如下图image(https://imghelloworld.o
Stella981 Stella981
3年前
Android内存溢出分析
   内存溢出,是Android开发中常遇到的问题,解决起来总是摸不着头脑。今天爬爬就来讲讲如何定位内存溢出。OOM(内存溢出)和MemoryLeak(内存泄露)有什么关系?OOM可能是因为MemoryLeak,也可能是你的应用本身就比较耗内存(比如图片浏览型的,或者应用本身的
Stella981 Stella981
3年前
Netty如何监控内存泄露
Netty如何监控内存泄露\TOC\前言一般而言,在Netty程序中都会采用池化的ByteBuf,也就是PooledByteBuf以提高程序性能。但是PooledByteBuf需要在使用完毕后手工释放,否则就会因为PooledByteBuf申请的内存空间没有归还进而造成内存泄露,最终OOM。而一旦
Wesley13 Wesley13
3年前
Java 内存区域和GC机制
Java垃圾回收概况  JavaGC(GarbageCollection,垃圾收集,垃圾回收)机制,是Java与C/C的主要区别之一,作为Java开发者,一般不需要专门编写内存回收和垃圾清理代码,对内存泄露和溢出的问题,也不需要像C程序员那样战战兢兢。这是因为在Java虚拟机中,存在自动内存管理和垃圾清扫机制。概括地说,该机制对JVM
Wesley13 Wesley13
3年前
Java内存区域与内存溢出异常
Java的内存管理是一个老生常谈的问题,虽然Java号称可以自动管理自己的内存,使程序员从内存管理的围墙解放出来,但是一连串的内存泄漏和溢出方面的问题,使得我们不得不去深入了解Java的内存管理机制。本篇文章将从Java的内存区域开始剖析Jvm的内存机制,阐述内存溢出异常产生的原因。运行时数据区域众说周知,Java程序是运行在Java虚拟机
Stella981 Stella981
3年前
JVM笔记二:Java内存区域
Java程序在虚拟机自动内存管理的机制的帮助下,不容易出现内存泄露和内存溢出问题,这也就要求程序员需要了解虚拟机处理内存的机制,以解决OOM问题。运行时数据区域!Java虚拟机运行时数据区(https://oscimg.oschina.net/oscnet/3755e1d9e9bf4068b2b3b77b4c0b6bf99b8.jpg)
Stella981 Stella981
3年前
JVM探秘3:内存溢出
在Java虚拟机内存区域中,除了程序计数器外,其他几个内存区域都可能会发生OutOfMemoryError,这次通过一些代码来验证虚拟机各个内存区域存储的内容。在实际工作中遇到内存溢出异常时,需要做到能根据异常信息快速判断是哪个内存区域的溢出,知道什么样的代码会导致这些区域内存溢出,并且知道出现内存溢出后如何处理。Java堆溢出Jav
Easter79 Easter79
3年前
ThreadLocal的内存泄露的原因分析以及如何避免
前言在分析ThreadLocal导致的内存泄露前,需要普及了解一下内存泄露、强引用与弱引用以及GC回收机制,这样才能更好的分析为什么ThreadLocal会导致内存泄露呢?更重要的是知道该如何避免这样情况发生,增强系统的健壮性。内存泄露内存泄露为程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果