在 JVM 运行过程中,出现 OutOfMemoryError 的常见触发场景具体包含哪些?请分类说明各类 OOM 的成因和典型表现。
考察说明
考查对 JVM 内存模型和 OOM 类型的理解
回答思路
- 【回答框架 1】JVM 规范规定了几种标准的 OutOfMemoryError,覆盖堆、方法区、直接内存、线程栈以及底层资源等不同区域。
- 【回答框架 2】堆内存不足是最常见的,当堆中对象存活率过高或分配速度超过回收速度时,会抛出 java heap space 错误。方法区和运行时常量池溢出通常与大量动态生成类或字符串 intern 有关。
- 【回答框架 3】直接内存溢出与 NIO 使用相关,当分配的堆外内存超过 -XX:MaxDirectMemorySize 限制且未及时回收时发生。线程栈溢出一般由递归过深或线程数过多导致,抛出 unable to create new native thread。
- 【回答框架 4】还有几种相对特殊的情况,例如元空间溢出,常因加载过多类或动态代理生成类过多;以及请求的数组长度超过虚拟机限制导致的 Requested array size exceeds VM limit。
- 【回答框架 5】实际排查时,需要结合内存快照分析工具、GC 日志和不同区域的配置参数来定位具体类型和根因。
- 【关键点 1】堆内存不足对应 java heap space,方法区或元空间不足对应 Metaspace,直接内存不足对应 Direct buffer memory,线程栈不足对应 unable to create new native thread。
- 【关键点 2】使用 -Xmx、-XX:MaxMetaspaceSize、-XX:MaxDirectMemorySize 可配置各区域上限,但需要根据应用实际需求和资源限制调整。
- 【关键点 3】OOM 可能由内存泄漏导致,也可能是内存分配冲击,二者需要区分处理。
- 【易错点 1】不要将所有 OOM 都归为堆溢出,直接内存和元空间溢出同样常见且表现不同。
- 【易错点 2】不要忽略操作系统层面的内存限制,容器内存限制可能引起无法创建线程等异常。