01-JVM 虚拟机面试题
对应原始资料:
10-面试热点课件/JVM优化及面试热点分析.md、12-BAT/09-JVM虚拟机篇
一、JVM 内存结构
Q1:说一说 JVM 运行时数据区
| 区域 | 线程私有 | 存放 | 异常 |
|---|---|---|---|
| 程序计数器 PC | 是 | 当前指令地址 | 无 |
| 虚拟机栈 | 是 | 栈帧(局部变量、操作数栈) | StackOverflowError / OOM |
| 本地方法栈 | 是 | native 方法 | 同上 |
| 堆 Heap | 否 | 对象、数组(GC 主战场) | OutOfMemoryError |
| 方法区(元空间 Metaspace,JDK 8+) | 否 | 类信息、常量池、静态变量 | OOM |
JDK 8 把永久代(PermGen)替换为元空间(Metaspace),元空间用本地内存,不容易 OOM。 字符串常量池 JDK 7 起从永久代搬到堆。
Q2:堆的分代
- 新生代 = Eden : S0 : S1 = 8 : 1 : 1。
- 老年代:长期存活的对象。
- 大对象直接进老年代。
二、对象创建与内存
Q3:new 一个对象的过程
- 类加载检查。
- 分配内存(指针碰撞 / 空闲列表)。
- 内存空间初始化为零值。
- 设置对象头(Mark Word、类型指针、数组长度)。
- 执行
<init>构造方法。
Q4:对象内存布局
- 对象头:Mark Word(hash、GC 年龄、锁状态)、类型指针。
- 实例数据:字段。
- 对齐填充:8 字节对齐。
三、垃圾回收(GC)
Q5:如何判断对象死亡
- 引用计数法(不用,循环引用问题)。
- 可达性分析:从 GC Roots 出发能否到达。GC Roots:
- 栈中局部变量引用。
- 方法区静态变量、常量引用。
- 本地方法栈 JNI 引用。
Q6:四种引用
- 强引用
Object o = new ...:永不回收(除非置 null)。 - 软引用
SoftReference:内存不足才回收(缓存)。 - 弱引用
WeakReference:下次 GC 必回收(ThreadLocal、WeakHashMap)。 - 虚引用
PhantomReference:跟踪对象被回收(管理直接内存)。
Q7:GC 算法
- 标记-清除:碎片多。
- 标记-复制:新生代用,浪费空间。
- 标记-整理:老年代用,慢但无碎片。
- 分代收集:新生代复制、老年代整理。
Q8:常见的垃圾收集器
| 收集器 | 代 | 特点 |
|---|---|---|
| Serial / Serial Old | 新/老 | 单线程,client 模式 |
| ParNew | 新 | Serial 多线程版 |
| Parallel Scavenge / Parallel Old | 新/老 | 吞吐量优先(JDK 8 默认) |
| CMS | 老 | 低延迟,标记清除(已废弃) |
| G1 | 全堆 | Region 化,可预测停顿(JDK 9+ 默认) |
| ZGC / Shenandoah | 全堆 | 染色指针,亚毫秒停顿 |
Q9:什么时候触发 Full GC
- 老年代满。
- 元空间满。
System.gc()(建议,非强制)。- 担保失败 / 并发失败。
Q10:GC 调优思路
- 看日志/GC 日志:
-Xloggc、jstat、VisualVM、arthas。 - 关注吞吐量、停顿时间、GC 频率。
- 合理设置
-Xms -Xmx(相等避免扩容)、新生代老年代比例。
四、类加载机制
Q11:类加载过程
加载 → 验证 → 准备 → 解析 → 初始化 → 使用 → 卸载
- 准备:静态变量分配内存赋默认值(0)。
- 初始化:执行
<clinit>(静态代码块 + 静态变量赋值)。
Q12:双亲委派模型
加载时先委托父加载器加载,失败才自己加载。
启动类加载器(rt.jar)
↑
扩展类加载器(ext/*.jar)
↑
应用类加载器(classpath)
↑
自定义加载器作用:防止核心类被篡改、避免重复加载。
Q13:打破双亲委派的场景
- SPI:JDBC 用
Thread.contextClassLoader。 - Tomcat:每个 webapp 独立 ClassLoader,隔离应用。
- 热部署:自定义 ClassLoader 重新加载类。
五、内存溢出排查
Q14:OOM 怎么排查
- 看
java.lang.OutOfMemoryError的类型:Java heap space:堆溢出,可能内存泄漏。GC overhead limit exceeded:GC 花费 > 98% 时间但回收 < 2%。Metaspace:类太多(动态生成、CGLIB)。Direct buffer memory:NIO 直接内存。
- 加参数
-XX:+HeapDumpOnOutOfMemoryError,dump 堆。 - 用 MAT / jvisualvm 分析 hprof,找大对象和引用链。
- 用 arthas 在线诊断。
六、JVM 调优参数常用
-Xms2g -Xmx2g # 初始/最大堆
-Xmn1g # 新生代
-XX:MetaspaceSize=256m
-XX:MaxMetaspaceSize=512m
-XX:+UseG1GC
-XX:MaxGCPauseMillis=200
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/log/oom.hprof高频考点速记
- JVM 三大区域:堆(GC)、栈(线程私有)、方法区(元空间)。
- 判活:可达性分析 + GC Roots。
- 双亲委派 = 安全 + 避免重复加载。
- G1:Region + 可预测停顿。
- CMS 四阶段:初始标记 → 并发标记 → 重新标记 → 并发清除。