内存泄漏是对象该回收未回收致堆空间渐少,内存溢出是分配时无足够内存而崩溃;需分四步排查:确认类型、三段快照比对、锁定四类高危模式、闭环验证修复。
内存泄漏和内存溢出是 Java 应用线上故障的高频原因,但二者常被混淆。简单说:内存泄漏是对象该回收却没被回收,长期累积导致可用堆空间越来越少;内存溢出(OutOfMemoryError)是某次分配时连“最后一块够用的内存”都找不到,直接崩溃。排查不能只看现象,得有一套分层定位、证据闭环的框架。
不是所有 OutOfMemoryError 都等于内存泄漏。先快速归因:
java.lang.OutOfMemoryError: Java heap space,且发生在应用启动后几分钟内:大概率是堆配置过小或单次加载数据超限(如一次查 100 万条记录转 List),属于溢出,非泄漏;Unable to create new native thread 或 Metaspace 相关 OOM:说明问题不在堆,可能线程泄漏或类加载器未释放,需切换排查维度。不依赖复杂平台,仅靠 JDK 自带工具就能发现 80% 的泄漏线索。关键在“同一业务操作前后”的对比:
kill -3 触发一次 Full GC):获取当前存活对象统计,重点关注数量异常多、单个实例大的类(如 byte[]、自定义缓存 Map、未关闭的连接池对象);90% 的泄漏来自固定场景,按优先级逐项排除:
public static Map<String, Object> cache = new HashMap<>();,忘了设过期或清理机制;改完代码别急着上线。验证要闭环:
jmap -histo:live,确认可疑类实例数不再增长;-XX:+PrintGCDetails 观察 Reference 处理日志)。这套框架不追求一步到位,而强调“现象→指标→快照→模式→验证”的证据链。很多团队卡在第一步就靠猜,结果修了三天发现根本不是泄漏。稳住节奏,用数据说话,问题自然浮出水面。