标准答案

  1. 堆主要保存对象和数组,重点看存活对象、缓存、队列和老年代增长。
  2. 栈由线程数量、栈深度和局部变量影响,递归或线程过多可能造成栈空间压力。
  3. 元空间保存类元数据,动态生成类、类加载器泄漏和代理类过多可能使其增长。
  4. 调整内存上限只能缓解容量不足,不能替代对象、线程或类加载器生命周期修复。

题目解析

Java heap space 指向堆分配失败,StackOverflowError 更常见于单线程栈深度或栈帧过大,Metaspace OOM 则要看类元数据和类加载器生命周期。错误类型能缩小范围,但不能直接说明根因。

进程 RSS 还可能包含线程栈、直接内存、代码缓存、JNI 和 native 库。扩大 Xmx 甚至可能挤压这些区域,导致系统级 OOM 或容器被杀。

诊断要结合堆转储、线程转储、Native Memory Tracking、类加载统计和 GC 日志,确认是容量配置、无界缓存、递归、线程过多还是类加载器泄漏。

常见误区

  • 误区:所有 OOM 都只增加 -Xmx。改正:先按堆、元空间、直接内存、线程和 native 资源分类,再调整对应边界。
  • 误区:把 StackOverflowError 当成堆溢出。改正:检查递归、调用深度、线程栈大小和线程数量。
  • 误区:忽略类加载器泄漏。改正:观察类数量、加载器实例和动态代理/热部署生命周期,必要时做类元数据取证。

作者信息