目录
概述
OOM是out of memory的简称,表示程序需要的内存空间大于JVM分配的内存空间。OOM后果就是导致程序崩溃;可以通俗理解:程序申请内存过大,虚拟机无法满足。
导致OOM错误的情况一般是:
1.给JVM虚拟机分配的内存太小,实际业务需求对内存的消耗比较多
2.Java应用里面存在内存泄漏的问题,或者应用中有大量占用内存的对象,并且没办法及时释放。
给大家解释一下内存泄漏和内存溢出是两个完全不一样的情况:
内存泄露:申请使用完的内存没有释放,导致虚拟机不能再次使用该内存,此时这段内存就泄露了,因为申请者不用了,而又不能被虚拟机分配给别人用。
内存溢出:申请的内存超出了JVM能提供的内存大小,此时称之为溢出。
常见的OOM异常情况有两种:
1、java.lang.OutOfMemoryError:Java heap space------>java堆内存溢出,此种情况最常见,一般由于内存泄露或者堆的大小设置不当引起。对于内存泄露,需要通过内存监控软件查找程序中的泄露代码,而堆大小可以通过虚拟机参数-Xms,-Xmx来修改。
2、java.lang.OutOfMemoryError:PermGen space或java.lang.OutOfMemoryError:MetaSpace------>java方法区,溢出了,一般出现在大量Class、或者采用cglib等反射机制的情况,因为这些情况会产生大量的Class信息存储于方法区。
这种情况可以通过更改方法区的大小来解决,使用类似-XX:PermSize=64m-XX:MaxPermSize=256m的形式修改。
另外,过多的常量尤其是字符串也会导致方法区溢出。
遇到这类问题,通常的排查方式是,先获取内存的Dump文件。
Dump文件有两种方式来生成:
第一种是配置JVM启动参数,当触发了OOM异常的时候自动生成。
第二种是使用jmap工具来生成。
使用MAT工具来分析Dump文件:
1、如果是内存泄漏,可进一步通过工具查看泄漏对象到GC Roots的引用链。掌握了泄漏对象的类信息和GC Roots引用链的信息,就可以比较准确地定位泄漏代码的位置。
2、如果是普通的内存溢出,确实有很多占用内存的对象,那就只需要提升堆内存空间即可。