题目重点:解释堆、栈、方法区和运行时常量池,并区分 happens-before 与可见性。
题意与假设
这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。
- “内存模型”可能指运行时区域或 Java 并发内存语义;先澄清并分别给出答案。
- JVMS 描述抽象区域,物理布局与垃圾回收策略依赖实现。
解题路线
- 线程共享堆存放对象;每线程 JVM 栈含调用帧、局部变量和操作数栈,程序计数器记录执行位置;方法区承载类相关结构,运行时常量池属于相应类/接口。
- 不要把抽象规范的每个区域硬套成固定操作系统内存段。优化可能消除分配或改变表示,不能用“所有对象一定物理在堆”描述 JIT。
- Java Memory Model 解决线程间读写的顺序与可见性。同步、volatile 与线程启动/等待形成规定的 happens-before 关系。
- volatile 引用发布不等于集合内部后续复合操作原子;安全构造与后续访问合同要分别证明。
手动走一遍
方法调用深递归可能耗尽栈;大量仍被缓存引用的对象占用堆。二者的原因与排查路径不同。两个线程对普通 int 做 ++ 会丢更新;把字段改 volatile 仍不使 read-modify-write 成为原子操作。
规模与取舍
栈需求随调用深度与帧大小增长,堆随存活对象增长;线程数量也影响内存。对性能给出测量而非固定字节承诺。
易错点与追问
容易失分的边界
- 把 JMM 与堆栈区域混为一谈。
- volatile 能解决所有竞态。
- 把 metaspace 实现术语当所有 JVM 规范。
继续深挖
- 如何安全发布配置快照?
- 区分 StackOverflowError 与 OutOfMemoryError 的证据是什么?
技术参考
- JVMS 运行时数据区域:技术语义参考,具体题目按本文约定。
