
什么是OOM?
OOM,全称“Out Of Memory”,即内存溢出错误,源自java.lang.OutOfMemoryError。当Java虚拟机因为内存不足无法分配对象空间,且垃圾回收器无法提供更多的可用内存时,就会抛出此错误。
为什么会发生OOM?
OOM的主要原因可以归结为两点:
1. 分配的内存过少:例如,虚拟机可使用的内存(通常通过启动时的VM参数指定)太少。
2. 应用程序使用的内存过多且未正确释放,导致内存或内存溢出。
内存是指申请使用的内存未释放,导致虚拟机无法再次使用,而这部分内存就了。内存溢出则是申请的内存超过了JVM能提供的内存大小。
在早期的编程语言如C和C++中,需要手动管理内存的申请和释放。如果申请了内存后忘记释放,比如C++中的new了但是没有delete,就会导致内存。偶尔的内存可能不会有明显问题,但大量的内存会导致内存溢出。
而在Java中,由于存在垃圾自动回收机制,通常不需要主动释放不再使用的对象所占的内存。但在编码不当的情况下,如将对象引用放入全局的Map中,可能导致对象无法被及时回收,从而出现内存的情况。逻辑上的原因在Java中的内存与C++中的忘记delete有所不同。
OOM的类型
按照JVM规范,Java虚拟机在运行时会管理以下内存区域:程序计数器、Java虚拟机栈、本地方法栈、Java堆、方法区、运行时常量池和直接内存。除了程序计数器外,其他内存区域都可能会抛出OOM。
最常见的OOM情况有以下三种:
3. java.lang.StackOverflowError – 这是另一种常见的Java内存溢出错误,通常由死循环或深度递归调用造成。可以通过虚拟机参数-Xss来设置栈的大小。
OOM分析–heapdump
为了分析OOM的原因,可以采用以下两种方式获取堆的内存镜像:
1. 设置JVM参数-XX:+HeapDumpOnOutOfMemoryError,在发生OOM时自动生成堆信息dump文件。不过此方法需要JDK5及以上版本支持。
2. 使用JDK自带的jmap命令生成堆dump文件。”jmap -dump:format=b,file=heap.bin ” 其中pid可以通过jps获取。
