文章目录
一、OOM是什么?二、分类1.Java heap space2.PermGen space(Java 7及之前版本)3.Metaspace(Java 8及之后版本)4.Direct buffer memory5.Stack overflow
三、避免OOM错误1.合理设置JVM参数2.代码优化3.避免内存泄漏4.优化垃圾收集
一、OOM是什么?
OOM是"Out of Memory"的缩写,中文意思是“内存不足”。在计算机科学中,当一个程序尝试使用比系统可用内存更多的内存时,就会发生OOM错误。这种情况通常发生在程序试图分配内存空间,但操作系统无法满足请求,因为它已经没有足够的空闲内存来提供给该程序。
二、分类
在Java中,OOM(Out of Memory)错误通常发生在JVM(Java虚拟机)无法为新对象分配内存空间时。这通常意味着堆内存(Heap Memory)已经满了,并且垃圾回收器(Garbage Collector, GC)无法释放足够的空间来满足新的内存请求。Java中的OOM错误可以分为几种类型,根据发生的具体情况不同而有所区别。
1.Java heap space
这是最常见的OOM类型之一,表示JVM的堆内存不足。堆是用于存储对象实例的地方,当程序尝试创建大量对象或者存在内存泄漏时容易触发此类错误。解决方法包括:
增加-Xmx参数设置的最大堆大小优化代码减少不必要的对象创建使用更有效的数据结构和算法检查并修复内存泄漏问题
2.PermGen space(Java 7及之前版本)
永久代(Permanent Generation)存放了类的元信息、常量池等数据。如果加载了太多类或有大型的类加载器泄露,可能会导致此区域溢出。自Java 8起,永久代被元空间(Metaspace)取代,后者使用本地内存而非JVM堆内存。
解决方案:对于Java 7及以前版本,可以通过增加-XX:MaxPermSize参数来增大永久代的空间;对于Java 8及以上版本,则需要调整-XX:MaxMetaspaceSize参数
3.Metaspace(Java 8及之后版本)
从Java 8开始引入了元空间代替永久代,它默认使用的是本机内存。如果元空间配置不当或应用程序动态生成了大量的类,也可能遇到OOM异常。
调整-XX:MaxMetaspaceSize来控制元空间的最大尺寸
4.Direct buffer memory
直接缓冲区(Direct Buffers)是通过ByteBuffer.allocateDirect()方法创建的,它们不位于堆上而是直接映射到物理内存。过多地使用这类缓冲区可能导致直接内存溢出。
可以通过设置-XX:MaxDirectMemorySize来自定义最大直接内存大小
5.Stack overflow
虽然严格来说不属于OOM,但栈溢出(StackOverflowError)也是由于内存限制引起的问题。当递归调用过深或线程栈太小的时候会发生这种情况。
适当调整-Xss参数可以改变每个线程的栈大小
三、避免OOM错误
1.合理设置JVM参数
2.代码优化
减少不必要的对象创建 :尽量重用对象而不是频繁地创建新对象使用合适的数据结构 :选择合适的数据结构能够有效降低内存消耗避免大对象 :如果必须处理大量数据,考虑分批加载或使用流式处理及时释放资源 :确保文件、数据库连接等外部资源在使用后被正确关闭
3.避免内存泄漏
检查静态集合类 :长时间运行的应用中,静态集合类容易成为内存泄漏的来源清除不再使用的引用 :确保不再使用的对象引用被置为null,这样垃圾回收器可以回收这些对象使用弱引用 :当某些对象只有在内存不足时才允许被回收,可以考虑使用WeakReference分析工具 :利用像VisualVM, JProfiler这样的工具来监控应用的内存使用情况,并定位潜在的内存泄漏问题
4.优化垃圾收集
选择合适的GC算法 :根据应用特性选择适合的垃圾收集器,如G1 GC适用于大内存环境下的低延迟要求。调优GC参数 :适当调整GC相关的JVM参数,比如年轻代与年老代的比例、新生代的大小等,以提高垃圾收集效率