JVM——内存泄漏与内存溢出

JVM——内存泄漏与内存溢出

  1. 内存溢出:squirrel:
  2. 1 什么是 Java 的内存溢出? 在 Java 程序运行的过程中,经常会碰到以下错误:java.lang.OutOfMemoryError。 通俗讲,内存溢出是指程序在申请内存时,没有足够的内存空间供其使用,出现 OutOfMemoryError。

1.2 产生原因? 简单来讲为以下两点:

  1. JVM 内存过小
  2. 产生过多的,没有被回收的垃圾

以下讨论主要基于 JVM 上不同内存区域的讨论 1.3 Java 堆溢出 Java 堆是存放对象实例的地方,当我们不断申请创建对象,并且保证这些对象始终可以从 GC Roots 可达,总容量就会触及最大堆的容量限制而抛出内存溢出异常 例如以下代码,将虚拟机的初始大小设为 20M ,并且不可变(将堆的最小值 -Xms 和 堆的最大值 -Xmx 设置为一样可以避免 Java 堆自动扩展!)

public class OOM {
    /*
        -Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError 
    */
    static class OOMObject{

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

JVM——内存泄漏与内存溢出

解决方法:boom: 常规处理方法是通过内存映像分析工具对 Dump 出来的堆转储快照进行分析。

  1. 首先分析是内存泄漏还是内存溢出
  2. 如果是内存泄漏通过工具查看泄露对象到 GC Roots 的引用链,分析垃圾收集器无法回收他们的原因,进而定位到出现问题的代码
  3. 如果不是内存泄漏,即对象都应该必须活着,就应该对比 JVM 堆内存 和机器内存相比是否还有向上调整的空间;或者从代码上检查某些对象是否生命周期过长,持有状态时间过长,存储结构设计不合理等,尽量减少程序运行期间的内存消耗

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

  1. 如果线程请求栈的深度大于虚拟机所允许的最大深度,将抛出 StackOverflowError 异常
  2. 如果虚拟机的栈内存允许动态的扩展,当扩展栈的容量无法申请到足够的内存的时候,将抛出’OutOfMemoryError’异常 解决方法:boom:
  3. 出现 StackOverflowError 异常时,会有明确错误堆栈可供分析,比较容易定位问题所在,例如递归没有终止条件。栈深度大多数情况下到达 1000-2000 是没有问题的,对于正常方法的调用,这个深度完全是够用的。
  4. 但如果是因为建立过多线程导致内存溢出,在不能减少线程的数量的情况下,只能通过减少最大堆的容量或者减少栈的容量来获取更多的线程!

1.5 方法区和运行时常量池溢出 由于在 JDK 8 以后,永久代退出了历史舞台,元空间作为其替代者登场,即元空间使用的是直接内存,受限于本机物理内存的大小,不再容易抛出方法区的内存溢出。而在 JDK 8 之前,方法区的实现永久代是会因为加载了大量的类(比如 CG Lib 字节码技术)而抛出方法区内存溢出的,或者因为运行时常量池(JDK 6 还是属于方法区的一部分,抛出的是方法区的内存溢出;而 JDK7之后便移到 Java 堆上,抛出的是 java 的堆内存溢出)而抛出对应区域的内存溢出!

1.6 本机直接内存溢出 直接内存可以通过 -XX:MaxDirectMemorySize 参数来指定,若不指定则默认与堆的最大值保持一致。 由直接内存导致的内存溢出,一个明显的特征就是在 dump 下的文件不会看到有明显的异常情况,或者该文件很小,而程序又直接或者间接的使用了 Direct Memory ,就应该去考虑是否是本机直接内存溢出

  1. 内存泄漏:squirrel: Memory Leak,是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光。 在 Java 中,内存泄漏就是存在一些被分配的对象,这些对象有下面两个特点:

首先,这些对象是可达的,即在有向图中,存在通路可以与其相连; 其次,这些对象是无用的,即程序以后不会再使用这些对象。 如果对象满足这两个条件,这些对象就可以判定为 Java 中的内存泄漏,这些对象不会被 GC 所回收,然而它却占用内存。

  1. 两者联系 内存泄露会最终会导致内存溢出。 相同点:都会导致应用程序运行出现问题,性能下降或挂起。 不同点:
  2. 内存泄露是导致内存溢出的原因之一,内存泄露积累起来将导致内存溢出。
  3. 内存泄露可以通过完善代码来避免,内存溢出可以通过调整配置来减少发生频率,但无法彻底避免。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值