很多同学面试 JVM 很痛苦:知识点杂乱、背了不会用、面试问深一点就崩。本文按照入门基础 → 内存模型 → GC 垃圾回收 → 类加载机制 → 底层原理 → 线上调优与故障排查难度逐级递增整理,可直接背诵、可直接口述、可解决线上问题。
适合:Java 初级/中级/高级面试突击、简历亮点补充、后端技术复盘。
一、入门基础篇(初级必问,送分题)
1. 什么是 JVM?它的作用是什么?
**答:**JVM 即 Java 虚拟机,是一台专门执行 Java 字节码的虚拟机器。
核心作用三点:
✅跨平台:一次编译、到处运行,
.java编译为统一.class字节码,由各平台 JVM 执行;✅自动内存管理:自动分配内存、自动垃圾回收,避免 C/C++ 手动内存出错;
✅代码安全与隔离:字节码校验、沙箱机制,保障运行安全。
2. JDK、JRE、JVM 三者区别?
**答:**包含关系:JDK > JRE > JVM
JVM:只负责运行字节码,无编译工具;
JRE:JVM + Java 基础类库,只能运行程序,不能开发;
JDK:JRE + 编译、调试、监控工具,完整开发环境。
3. Java 程序运行过程?
答:
编写.java→javac编译成.class字节码 → JVM 类加载 → 字节码校验 → 解释/编译执行 → 自动内存管理与 GC。
4. Java 是跨平台的,JVM 是跨平台的吗?
答:Java 跨平台,JVM 不跨平台。
不同操作系统需要安装对应版本的 JVM,JVM 屏蔽系统差异,从而实现 Java 字节码跨平台运行。
二、JVM 内存结构篇(中级高频核心)
1. JVM 运行时数据区有哪些?哪些线程私有、哪些共享?
答:
线程私有(随线程生灭):
程序计数器:记录当前执行字节码行号,唯一无 OOM 区域;
虚拟机栈:存储栈帧、局部变量表、方法调用与返回信息;
本地方法栈:为虚拟机使用到的本地(Native)方法服务。
线程共享(全局):
堆 Heap:所有对象、数组存放位置,GC 主战场;
元空间 Metaspace(JDK8):存类结构、方法、常量、静态变量。
2. 栈和堆的区别?
答:
栈:线程私有、速度快、空间小、方法结束自动释放、无 GC;
堆:线程共享、空间大、速度慢、需要 GC 回收、容易 OOM。
口诀:栈存局部变量,堆存对象实例。
3. JDK8 为什么废除永久代、改用元空间?
答:
永久代大小固定,容易出现PermGen OOM;
元空间使用本地直接内存,不再占用堆内存;
动态扩容,默认几乎无上限,大幅减少类加载 OOM。
4. 常见 OOM 内存溢出场景?
**答:**四种最常见:
堆 OOM:对象过多、内存泄漏、大对象堆积;
元空间 OOM:动态生成大量类、CGLIB 代理、频繁热部署;
栈溢出:递归死循环、方法调用层级过深(StackOverflowError);
直接内存 OOM:NIO 未释放 ByteBuffer。
5. 深拷贝和浅拷贝?
答::
浅拷贝(shallowCopy)只是增加了一个指针指向已存在的内存地址
深拷贝(deepCopy)是增加了一个指针并且申请了一个新的内存,使这个增加的指针指向这个新的内
存
三、GC 垃圾回收篇(面试重中之重)
1. JVM 如何判断对象是否可回收?
**答:**主流采用可达性分析算法。
从GC Roots出发遍历对象图,不可到达的对象即为垃圾对象。
GC Roots 包含:栈中引用对象、静态变量、常量、本地方法引用、活跃线程。
补充:早期引用计数法,无法解决循环引用,已被 JVM 废弃。
2. JVM 四种引用类型及场景?
**答:**强度从高到低:强 > 软 > 弱 > 虚
强引用:默认引用,只要存在就不回收(普通业务对象);比如 Object obj = new Object();
软引用 SoftReference:内存充足不回收,内存即将 OOM 才回收,适合做缓存;
弱引用 WeakReference:下次 GC 必回收,适用于ThreadLocal;
虚引用 PhantomReference:仅用于监控对象回收,不能获取对象实例。
3. 新生代与老年代特点?对象晋升规则?
答:
新生代(Eden + S0 + S1)8:1:1:对象新生、存活少、GC 频繁、速度快;
老年代:存活久、体积大、GC 少、耗时高。
晋升条件:
对象新生代存活满15 次 GC晋升老年代;
大对象直接进入老年代,避免新生代复制开销。
4. Minor GC、Major GC、Full GC 区别?
答:
Minor GC:只回收新生代,频率高、STW 短,影响小;
Major GC:主要回收老年代,通常伴随 Minor GC;
Full GC:全堆回收(新生代+老年代+元空间),STW 最长、最耗性能,线上尽量避免。
5. 常见垃圾收集器对比与生产选型?
答:
Parallel:吞吐量优先,JDK8 默认,适合后台任务、批量服务;
CMS:低延迟、并发回收,适合高并发互联网服务,缺点:内存碎片、浮动垃圾;
G1:分区收集、可控制停顿时间,JDK9+ 默认,均衡吞吐量与延迟;
ZGC:超低延迟、毫秒级停顿,适合超大堆、核心高可用服务。
四、类加载机制篇(中高阶必问)
1. 类加载的全过程?
**答:**五大阶段:加载 → 验证 → 准备 → 解析 → 初始化
加载:读取 class 文件,生成 Class 对象;
验证:校验字节码合法性、安全性;
准备:静态变量分配内存、赋默认值;
解析:符号引用转为直接内存引用;
初始化:执行静态代码块、静态变量赋值。
2. 什么是双亲委派模型?作用?
**答:**类加载器加载类时,先向上委托父加载器,父加载器无法加载,自己再加载。
加载器层级:启动类加载器 → 扩展类加载器 → 应用类加载器 → 自定义加载器
核心作用:
保证 JDK 核心类安全,防止被自定义类篡改(如 String、Object);
避免类重复加载,保证类唯一性。
3. 哪些场景会打破双亲委派?
**答:**四大经典场景:
JDBC、Dubbo 等SPI 服务扩展;
Tomcat 容器隔离不同项目类、热部署;
OSGi 模块化动态热更新;
自定义类加载器实现加密、热加载。
五、底层进阶篇(高级开发面试点)
1. 什么是 STW?哪些 GC 会产生 STW?
**答:**STW(Stop-The-World)即暂停所有用户线程,只保留 GC 线程工作,是程序卡顿的根本原因。
所有 GC 都会 STW,只是时长不同:
Minor GC:短暂 STW,几乎无感;
Full GC:长时间 STW,直接导致接口超时、服务卡顿。
2. 内存泄漏和内存溢出的区别?常见泄漏场景?
答:
内存泄漏:无用对象一直被引用,GC 无法回收,是持续过程;
内存溢出 OOM:泄漏累积到内存耗尽,是最终结果。
高频内存泄漏场景:
静态集合无限堆积数据不清理;
ThreadLocal 使用后未 remove,线程复用导致对象常驻内存;
IO、数据库、连接池资源未关闭;
缓存无过期、无淘汰策略;
匿名内部类、异步线程持有外部对象引用。
3. 对象在 JVM 中的创建流程?
答:
检测类是否已加载,未加载则执行类加载;
堆内存分配(指针碰撞 / 空闲列表);
初始化对象默认值;
设置对象头信息;
执行构造方法初始化;
返回对象引用。
六、线上调优与故障排查(大厂压轴题)
1. 生产常用 JVM 参数?
答:
-Xms初始堆内存、-Xmx最大堆内存(生产建议相等,避免动态扩容);-Xmn新生代大小;-XX:MetaspaceSize / MaxMetaspaceSize元空间参数;-Xss线程栈大小;-XX:+UseG1GC使用 G1 收集器;-XX:+PrintGCDetails打印 GC 日志。
2. 线上频繁 Full GC 如何排查?
**答:**标准排查流程:
查看 GC 日志,确认是内存泄漏还是内存不足;
jps查看进程、jstat -gc实时监控 GC 频率与耗时;jmap查看堆对象分布,dump 堆快照;使用 MAT/JProfiler 分析大对象、泄漏对象、重复对象;
定位代码问题:缓存、静态集合、ThreadLocal、资源未释放;
修复代码 + 调整 JVM 参数 + 压测验证。
3. 什么时候需要做 JVM 调优?
**答:**出现以下现象必须调优:
Full GC 频繁、GC 停顿时间过长;
接口响应抖动、超时、CPU 飙高;
服务频繁 OOM、重启、内存水位持续居高不下。
七、写在最后
JVM 面试的核心逻辑非常清晰:
初级:考概念、内存结构、GC 基础;
中级:考引用类型、回收机制、类加载、双亲委派;
高级:考收集器选型、STW、内存泄漏、线上 GC 调优、故障排查。
本文从易到难全覆盖,不仅适用于面试背诵,更能帮你建立完整的 JVM 底层思维。
如果对你有帮助,点赞、分享、推荐一下呀!对主编都是很大的帮助。
留一个疑问,欢迎评论区讨论
User user = new User() 做了什么操作,申请了哪些内存?