【OutOfMemoryError】项目过程中碰到的各种OOM总结

OOM产生原因

常见原因有以下几种:
1.内存中加载的数据量过于庞大,如一次从数据库取出过多数据;
2.集合类中有对对象的引用,使用完后未清空,使得JVM不能回收;
3.代码中存在死循环或循环产生过多重复的对象实体;
4.使用的第三方软件中的BUG;
5.启动参数内存值设定的过小;

对应的Log显示的错误提示如下:
1.tomcat:java.lang.OutOfMemoryError: PermGen space
2.tomcat:java.lang.OutOfMemoryError: Java heap space
3.weblogic:Root cause of ServletException java.lang.OutOfMemoryError
4.resin:java.lang.OutOfMemoryError
5.java:java.lang.OutOfMemoryError

项目一

内存溢出日志(1)


Crash日志:

Info: java.lang.Object.internalClone(Native Method)
java.lang.Object.clone(Object.java:241)
XXXXXXXXX.ARScanFragment.onNewFrame(ARScanFragment.java:259)
。。。
。。。
。。。
name: 
java.lang.OutOfMemoryError: Failed to allocate a 460812 byte allocation with 239440 free bytes and 233KB until OOM, max allowed footprint 268435456, growth limit 268435456

现象描述:
8分钟左右内存>500M导致内存溢出

图像数据byte[] data在处理过程中进行了clone()处理。结果发现内存会不断增加直到Crash。
在分析这个日志的时候发现这个图像数据是给so层处理类似图像识别的过程的。
结合so部门同事分析发现他们并没有对内存进行过回收和释放。也就是说图像数据byte[] data一直在java层系统进行自动回收的。那么问题就很明显了,java层并没有必要clone数据给so层。
业务中并没有改变图像数据byte数组的值,因此业务也不要求clone数据
于是去掉clone()后的现象是:
20分钟左右达到344M然后系统回收内存在260M左右。
于是预估内存波动范围260~350M
解决了当前图像数据内存使用

内存溢出日志(2)


参考博客

java.lang.OutOfMemoryError异常解决方法

转载于:https://blog.51cto.com/4789781/2167315

<think>嗯,用户现在遇到了Java项目中的OutOfMemoryError问题,需要解决方案。之前用户提供了FutureExample的代码示例,但那个是关于多线程和Future的,与内存溢出关系不大,可能是用户复制错了参考内容。用户的核心诉求很明确:解决生产环境中的OOM问题。用户可能正在面临线上服务崩溃的紧急情况,情绪比较焦虑。虽然ta只简单描述了问题,但这类问题通常需要系统性排查。考虑到OOM的复杂性,我决定从六个维度展开:现象确认、原因分析、诊断工具、解决方案、预防措施和实例演示。注意到用户提到的是"Javaproject",猜测可能是Web应用或后端服务。内存问题最棘手的是定位根源,所以重点要教用户如何获取诊断证据(特别是堆转储分析)。用户能提供FutureExample代码,说明有一定技术基础,可以接受专业工具的使用指导。在方案设计上,需要覆盖最常见的原因:内存泄漏(如未释放集合引用)、资源未关闭(如数据库连接池)、数据量激增(如大文件加载)。对于每种情况都要给出可操作的检查清单,比如用jstat看GC状态,用MAT分析dominant_tree。特意加入"伪OOM"的说明很重要——很多用户会把NativeMemory耗尽误认为HeapOOM。准备用visualvm的截图示例让诊断更直观,最后用线程栈泄漏的案例演示完整分析流程,这样用户能按模板操作。需要提醒用户注意工具使用的安全细节:比如在生产环境获取堆转储会造成服务暂停,必须评估影响。故障复现部分建议用户优先在预发环境测试dump操作,避免线上风险。</think> 针对Java项目的`OutOfMemoryError`问题,以下是系统级的解决方案和分析步骤: --- ### 一、问题本质分析 `OutOfMemoryError`表示**JVM堆内存耗尽**(多数情况)或**非堆内存不足**(如元空间)。根本原因为: - 内存泄漏(对象无法被GC回收) - 内存配置不足(如-Xmx设置过小) - 大对象/大文件处理不当 - 并发请求量突增 --- ### 二、诊断工具与步骤 #### 1. 确认错误类型 - **Heap OOM**:`java.lang.OutOfMemoryError: Java heap space` - **非堆OOM**:`java.lang.OutOfMemoryError: Metaspace` 或 `Direct buffer memory` #### 2. 实时监控工具 ```bash # 监控堆内存与GC jstat -gc <pid> 1000 # 每秒输出GC状态 # 查看堆中对象分布 jmap -histo <pid> | head -20 # 统计对象数量前20 ``` #### 3. 获取堆转储(关键步骤) ```bash jmap -dump:format=b,file=heapdump.hprof <pid> ``` 用 **Eclipse Memory Analyzer (MAT)** 分析 `heapdump.hprof`,定位内存占用最高的对象(Dominator Tree)。 --- ### 三、通用解决方案 #### ✅ 内存泄漏修复 | 常见泄漏场景 | 修复方案 | |--------------|----------| | **静态集合** | 用`WeakHashMap`代替`HashMap`,定期清理无用数据 | | **未关闭资源** | 在`finally`中关闭`InputStream`、数据库连接等 | | **线程局部变量** | 及时调用`ThreadLocal.remove()` | | **监听器未注销** | 在对象销毁时反注册事件监听 | #### ✅ 内存配置优化 ```bash # 调整堆大小(示例) java -Xms512m -Xmx2048m -XX:MaxMetaspaceSize=256m -jar app.jar # 针对G1垃圾回收器优化 -XX:+UseG1GC -XX:MaxGCPauseMillis=200 ``` #### ✅ 代码优化 - 避免在循环内创建大对象(如 `new byte[1024*1024]`) - 用`try-with-resources`自动管理资源 - 分页处理大文件/大数据集 - 缓存使用`SoftReference`或`WeakReference` --- ### 四、特殊场景处理 #### 1. **Metaspace OOM** ```bash # 增大元空间 -XX:MaxMetaspaceSize=512m # 记录类加载信息 -XX:+TraceClassLoading -XX:+TraceClassUnloading ``` 检查是否有重复加载类(如OSGi/热部署问题) #### 2. **堆外内存溢出** ```bash # 调整直接内存 -XX:MaxDirectMemorySize=256m ``` 排查:Netty、NIO等框架中未释放的`ByteBuffer` --- ### 五、预防措施 1. **压力测试**:用JMeter模拟高并发,观察内存变化 2. **监控告警**:集成Prometheus + Grafana监控: - JVM堆使用率 - GC频率与耗时 - 线程数峰值 3. **代码规范**:使用`@Slf4j`记录大对象创建日志 --- ### 六、故障复现示例 ```java // 模拟内存泄漏(静态Map持续增长) public class MemoryLeak { static Map<Object, Object> staticMap = new HashMap<>(); public static void main(String[] args) { while (true) { staticMap.put(new Object(), new byte[1024 * 1024]); // 每秒泄漏1MB Thread.sleep(1000); } } } ``` 运行参数:`java -Xms10m -Xmx20m MemoryLeak` 👉 分析堆转储可清晰定位`staticMap`的引用链。 --- > **关键提示**:80%的OOM可通过**堆转储分析**准确定位,避免盲目调大内存掩盖问题本质 [^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值