Java 面试题

JVM内存模型:堆栈方法区到底放什么

讲讲JVM内存模型。各个区域放什么数据?OOM都有哪几种?

为什么面试官会问这道题

生产Java故障绝大多数是OOM或泄漏。面试官期待你能从"症状→区域"定位——堆OOM、元空间OOM、栈溢出的排查思路完全不同。

如何回答

  1. 1

    五大区域:堆(共享,GC管)、栈(线程私有,栈帧)、方法区/元空间(类元数据,Java 8起取代PermGen)、PC寄存器、本地方法栈,再加堆外的直接内存。

  2. 2

    堆分年轻代(Eden+两个Survivor)和老年代。大多数对象朝生夕灭——分代假说。

  3. 3

    栈放局部变量和栈帧。StackOverflowError=递归过深。每个线程独立栈,Linux x64默认约1MB。

  4. 4

    元空间在堆外的本地内存。"Metaspace OOM"通常是类加载器泄漏(热重载、动态代理框架)。

  5. 5

    直接内存也在堆外。NIO ByteBuffer、Netty都在这里分配,可能堆还有富余但这里OOM。

参考回答示例

JVM内存我按故障模式来记。堆OOM——对象太多或泄漏,上heap dump用MAT分析。元空间OOM——类加载器泄漏,多半是热重载框架或动态生成类。StackOverflowError——递归太深,一般是意外的无限递归。DirectBuffer OOM——堆外内存,堆还有但操作系统不给了。每个线程默认1MB栈,1万线程就吃掉10GB,堆都没碰——这也是响应式框架要逃离"每请求一线程"模型的原因。

实用技巧

  • MaxMetaspaceSize默认无上限——一定要设,这样类加载器泄漏能快速暴露。

  • 线程栈大小是-Xss。要开多线程就调小,要深递归就调大。

  • 即答侠会标注每个答案针对哪种JVM OOM——不会让你把堆OOM和元空间OOM答混。

常见问题

为什么Java 8把PermGen换成元空间?

PermGen有固定上限,应用重启/重部署容易OOM。元空间自动从本地内存扩容,JVM能动态调整,不用人工调优容量。

字符串常量池在堆还是方法区?

Java 7起挪到了堆。String.intern()放入的字符串都在堆的字符串池里,由GC回收。

面试时担心忘词?即答侠实时助你

即答侠 AI 实时监听面试对话,自动识别问题并即时生成回答建议——无感辅助,让你从容应对每一道题。

免费试用即答侠