Java OOM 常见情况

https://www.jianshu.com/p/9daaccbe17f4

为什么会OOM?

为什么会没有内存了呢?原因不外乎有两点:

1)分配的少了:比如虚拟机本身可使用的内存(一般通过启动时的VM参数指定)太少。

2)应用用的太多,并且用完没释放,浪费了。此时就会造成内存泄露或者内存溢出

内存泄露:申请使用完的内存没有释放,导致虚拟机不能再次使用该内存,此时这段内存就泄露了,因为申请者不用了,而又不能被虚拟机分配给别人用。

内存溢出:申请的内存超出了JVM能提供的内存大小,此时称之为溢出。

最常见的OOM情况有以下三种:

  • java.lang.OutOfMemoryError: Java heap space ------>java堆内存溢出,此种情况最常见,一般由于内存泄露或者堆的大小设置不当引起。对于内存泄露,需要通过内存监控软件查找程序中的泄露代码,而堆大小可以通过虚拟机参数-Xms,-Xmx等修改。
  • java.lang.OutOfMemoryError: PermGen space ------>java永久代溢出,即方法区溢出了,一般出现于大量Class或者jsp页面,或者采用cglib等反射机制的情况,因为上述情况会产生大量的Class信息存储于方法区。此种情况可以通过更改方法区的大小来解决,使用类似-XX:PermSize=64m -XX:MaxPermSize=256m的形式修改。另外,过多的常量尤其是字符串也会导致方法区溢出。
  • java.lang.StackOverflowError ------> 不会抛OOM error,但也是比较常见的Java内存溢出。JAVA虚拟机栈溢出,一般是由于程序中存在死循环或者深度递归调用造成的,栈大小设置太小也会出现此种溢出。可以通过虚拟机参数-Xss来设置栈的大小。
  • 解决异常
    首先通过内存映射分析工具 如 Eclipse Memory Analyzer 堆 dump出的异常堆转储进行快照解析确认内存中的对象是否是必要的  也就是先分清楚是 内存泄漏 Memory Leak 还是Memory Overflow 如果是内存泄漏 可通过工具进一步查看泄露的对象到GC Roots的引用链 就能找到泄露对象是怎么通过路径与 GC Roots 相关联导致垃圾收集器无法回收他们如果不存在泄露 就检查堆参数 -Xmx 与 -Xms 与机器物理内存对比是否还可以调大 从代码上检测 是否是某些对象的生命周期过长持有状态时间过长 尝试减少代码运行期间的内存消耗
  • 4)OOM分析--heapdump

    要dump堆的内存镜像,可以采用如下两种方式:

    设置JVM参数-XX:+HeapDumpOnOutOfMemoryError,设定当发生OOM时自动dump出堆信息。不过该方法需要JDK5以上版本。

    使用JDK自带的jmap命令。"jmap -dump:format=b,file=heap.bin <pid>"  其中pid可以通过jps获取。

    dump堆内存信息后,需要对dump出的文件进行分析,从而找到OOM的原因。常用的工具有:

    mat: eclipse memory analyzer, 基于eclipse RCP的内存分析工具。详细信息参见:http://www.eclipse.org/mat/,推荐使用。 

### Java应用程序中OutOfMemoryError的原因分析 Java应用程序中的`OutOfMemoryError (OOM)`通常发生在JVM无法分配足够的内存来满足程序的需求时。具体来说,当堆空间不足而垃圾回收器也无法释放更多可用内存时,就会抛出此错误[^1]。 #### 堆溢出(Heap Space) 最常见OOM原因是由于对象过多或过大导致的堆空间耗尽。这可能是因为存在大量未被及时清理的大对象,或者是创建了过多的小型临时对象。如果应用频繁触发全量GC但仍未能解决问题,则表明可能存在严重的内存泄漏风险[^2]。 ```java // 不良实践:持续增加列表大小而不考虑容量限制 List<String> list = new ArrayList<>(); while(true){ list.add("data"); } ``` 为了诊断此类问题,可以启用详细的GC日志记录功能,并通过工具如VisualVM、MAT(Memory Analyzer Tool)等来进行深入分析。 #### 元数据区/永久代溢出(Metaspace/PermGen Space) 对于使用旧版本JDK的应用,默认情况下会有一个称为“永久代”的区域用于存储类元信息;而在较新的JRE/JDK8及以上版本中已被替换为更灵活的“元数据区”。当加载到虚拟机里的类数量超过设定阈值时也会引发OOM异常[^3]。 ```bash # 设置最大元数据区大小参数示例 -Xmx512m -XX:MaxMetaspaceSize=256m ``` 针对这种情况,应该审查代码逻辑减少不必要的动态代理操作次数以及第三方库依赖项数目,必要时调整相应配置选项增大该分区尺寸。 #### 线程栈溢出(Stack Overflow) 虽然严格意义上不属于传统意义上的OOM范畴,但如果单个线程所需栈帧数太多同样会造成类似的后果——即所谓的“stack overflow”,特别是在递归调用过深的情况下容易发生这种状况。此时应优化算法结构避免过度嵌套层次并适当提高默认线程栈高度设置以缓解症状。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值