Organized 50 interview questions into 12 categories: - 01-分布式系统 (9 files): 分布式事务, 分布式锁, 一致性哈希, CAP理论, etc. - 02-数据库 (2 files): MySQL索引优化, MyBatis核心原理 - 03-缓存 (5 files): Redis数据结构, 缓存问题, LRU算法, etc. - 04-消息队列 (1 file): RocketMQ/Kafka - 05-并发编程 (4 files): 线程池, 设计模式, 限流策略, etc. - 06-JVM (1 file): JVM和垃圾回收 - 07-系统设计 (8 files): 秒杀系统, 短链接, IM, Feed流, etc. - 08-算法与数据结构 (4 files): B+树, 红黑树, 跳表, 时间轮 - 09-网络与安全 (3 files): TCP/IP, 加密安全, 性能优化 - 10-中间件 (4 files): Spring Boot, Nacos, Dubbo, Nginx - 11-运维 (4 files): Kubernetes, CI/CD, Docker, 可观测性 - 12-面试技巧 (1 file): 面试技巧和职业规划 All files renamed to Chinese for better accessibility and organized into categorized folders for easier navigation. Generated with [Claude Code](https://claude.com/claude-code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering>
325 lines
7.0 KiB
Markdown
325 lines
7.0 KiB
Markdown
# JVM 和垃圾回收
|
||
|
||
## 问题
|
||
|
||
1. JVM 内存模型是怎样的?
|
||
2. 垃圾回收有哪些算法?G1 和 CMS 的区别?
|
||
3. 什么是 Stop-The-World?如何减少 STW 时间?
|
||
4. 常见的 OOM 及解决方案?
|
||
5. JVM 参数如何调优?
|
||
6. 如何分析 GC 日志?
|
||
|
||
---
|
||
|
||
## 标准答案
|
||
|
||
### 1. JVM 内存模型
|
||
|
||
#### **运行时数据区**
|
||
|
||
```
|
||
┌─────────────────────────────────────┐
|
||
│ 方法区(Method Area) │
|
||
│ (类信息、常量、静态变量、JIT 代码) │
|
||
└─────────────────────────────────────┘
|
||
┌─────────────────────────────────────┐
|
||
│ 堆(Heap) │
|
||
│ (对象实例、数组) │
|
||
│ ┌──────────┐ ┌──────────┐ │
|
||
│ │ 新生代 │ │ 老年代 │ │
|
||
│ │ Eden │ │ │ │
|
||
│ │ S0 │ │ │ │
|
||
│ │ S1 │ │ │ │
|
||
│ └──────────┘ └──────────┘ │
|
||
└─────────────────────────────────────┘
|
||
┌─────────────────────────────────────┐
|
||
│ JVM 栈(Java Stack) │
|
||
│ (栈帧:局部变量、操作数栈、返回地址) │
|
||
└─────────────────────────────────────┘
|
||
┌─────────────────────────────────────┐
|
||
│ 本地方法栈(Native Stack) │
|
||
│ (Native 方法调用) │
|
||
└─────────────────────────────────────┘
|
||
┌─────────────────────────────────────┐
|
||
│ 程序计数器(PC Register) │
|
||
│ (当前执行的字节码指令) │
|
||
└─────────────────────────────────────┘
|
||
```
|
||
|
||
---
|
||
|
||
### 2. 垃圾回收算法
|
||
|
||
#### **标记-清除(Mark-Sweep)**
|
||
|
||
**步骤**:
|
||
1. 标记存活对象
|
||
2. 清除未标记对象
|
||
|
||
**问题**:
|
||
- 产生内存碎片
|
||
- 标记和清除效率都不高
|
||
|
||
---
|
||
|
||
#### **复制(Copying)**
|
||
|
||
**步骤**:
|
||
1. 将存活对象复制到另一块内存
|
||
2. 清空当前内存
|
||
|
||
**优点**:
|
||
- 无内存碎片
|
||
- 简单高效
|
||
|
||
**缺点**:
|
||
- 内存利用率低(浪费一半)
|
||
|
||
**适用**:新生代(Eden + S0 + S1)
|
||
|
||
---
|
||
|
||
#### **标记-整理(Mark-Compact)**
|
||
|
||
**步骤**:
|
||
1. 标记存活对象
|
||
2. 将存活对象向一端移动
|
||
3. 清理边界外的内存
|
||
|
||
**优点**:
|
||
- 无内存碎片
|
||
|
||
**缺点**:
|
||
- 移动对象成本高
|
||
|
||
**适用**:老年代
|
||
|
||
---
|
||
|
||
#### **分代收集(Generational)**
|
||
|
||
**原理**:
|
||
- **弱分代假说**:大多数对象朝生夕灭
|
||
- **新生代**:复制算法(Eden : S0 : S1 = 8 : 1 : 1)
|
||
- **老年代**:标记-整理或标记-清除
|
||
|
||
---
|
||
|
||
### 3. 垃圾收集器
|
||
|
||
#### **Serial 收集器**
|
||
|
||
**特点**:单线程,STW
|
||
|
||
**适用**:客户端应用、小内存
|
||
|
||
```bash
|
||
-XX:+UseSerialGC
|
||
```
|
||
|
||
---
|
||
|
||
#### **Parallel 收集器**
|
||
|
||
**特点**:多线程,STW
|
||
|
||
**适用**:后台任务、批处理
|
||
|
||
```bash
|
||
-XX:+UseParallelGC
|
||
```
|
||
|
||
---
|
||
|
||
#### **CMS(Concurrent Mark Sweep)**
|
||
|
||
**特点**:并发收集,低停顿
|
||
|
||
**步骤**:
|
||
1. 初始标记(STW)
|
||
2. 并发标记
|
||
3. 重新标记(STW)
|
||
4. 并发清除
|
||
|
||
**问题**:
|
||
- CPU 敏感
|
||
- 浮动垃圾
|
||
- 内存碎片
|
||
|
||
```bash
|
||
-XX:+UseConcMarkSweepGC
|
||
```
|
||
|
||
---
|
||
|
||
#### **G1(Garbage First)**
|
||
|
||
**特点**:
|
||
- **可预测停顿**:用户指定停顿时间
|
||
- **分区回收**:将堆划分为多个 Region
|
||
- **优先回收垃圾多的 Region**
|
||
|
||
**适用**:大堆内存(> 6GB)、多核 CPU
|
||
|
||
```bash
|
||
-XX:+UseG1GC
|
||
-XX:MaxGCPauseMillis=200 # 目标停顿时间
|
||
```
|
||
|
||
---
|
||
|
||
#### **ZGC(Z Garbage Collector)**
|
||
|
||
**特点**:
|
||
- 并发整理(无内存碎片)
|
||
- 停顿时间 < 10ms
|
||
- 支持 TB 级堆内存
|
||
|
||
**适用**:超大内存、低延迟要求
|
||
|
||
```bash
|
||
-XX:+UseZGC
|
||
```
|
||
|
||
---
|
||
|
||
### 4. OOM 及解决方案
|
||
|
||
#### **Java.lang.OutOfMemoryError: Java heap space**
|
||
|
||
**原因**:堆内存不足
|
||
|
||
**解决**:
|
||
```bash
|
||
# 增加堆内存
|
||
-Xms4g -Xmx4g
|
||
|
||
# 使用 G1 收集器
|
||
-XX:+UseG1GC
|
||
```
|
||
|
||
---
|
||
|
||
#### **Java.lang.OutOfMemoryError: Metaspace**
|
||
|
||
**原因**:方法区(元空间)不足
|
||
|
||
**解决**:
|
||
```bash
|
||
# 增加元空间大小
|
||
-XX:MetaspaceSize=256m
|
||
-XX:MaxMetaspaceSize=512m
|
||
```
|
||
|
||
---
|
||
|
||
#### **Java.lang.OutOfMemoryError: GC overhead limit exceeded**
|
||
|
||
**原因**:GC 频繁,但回收内存少
|
||
|
||
**解决**:
|
||
- 增加堆内存
|
||
- 优化代码(减少对象创建)
|
||
|
||
---
|
||
|
||
#### **Java.lang.StackOverflowError**
|
||
|
||
**原因**:栈深度过大(递归太深)
|
||
|
||
**解决**:
|
||
```bash
|
||
# 增加栈大小
|
||
-Xss2m
|
||
```
|
||
|
||
---
|
||
|
||
### 5. JVM 参数调优
|
||
|
||
#### **常用参数**
|
||
|
||
```bash
|
||
# 堆内存
|
||
-Xms4g # 初始堆大小
|
||
-Xmx4g # 最大堆大小
|
||
-Xmn2g # 新生代大小
|
||
-XX:MetaspaceSize=256m
|
||
-XX:MaxMetaspaceSize=512m
|
||
|
||
# GC 选择
|
||
-XX:+UseG1GC
|
||
-XX:MaxGCPauseMillis=200
|
||
|
||
# GC 日志
|
||
-Xlog:gc*:file=/tmp/gc.log:time,tags:filecount=5,filesize=10m
|
||
|
||
# OOM 时自动 Dump
|
||
-XX:+HeapDumpOnOutOfMemoryError
|
||
-XX:HeapDumpPath=/tmp/
|
||
```
|
||
|
||
---
|
||
|
||
#### **调优步骤**
|
||
|
||
```
|
||
1. 监控 GC 频率和停顿时间
|
||
2. 分析 GC 日志
|
||
3. 调整堆内存和新生代比例
|
||
4. 选择合适的 GC 收集器
|
||
5. 优化代码(减少对象创建)
|
||
6. 压测验证
|
||
```
|
||
|
||
---
|
||
|
||
### 6. GC 日志分析
|
||
|
||
#### **工具**
|
||
|
||
- **GCViewer**:可视化分析
|
||
- **GCeasy**:在线分析(https://gceasy.io)
|
||
- **阿里 Arthas**:线上诊断
|
||
|
||
---
|
||
|
||
#### **GC 日志示例**
|
||
|
||
```
|
||
[GC (Allocation Failure) [PSYoungGen: 2048K->512K(2560K)] 2048K->1024K(9216K), 0.0023456 secs]
|
||
[Full GC (Ergonomics) [PSYoungGen: 512K->0K(2560K)] [ParOldGen: 512K->512K(6656K)] 1024K->512K(9216K), [Metaspace: 5120K->5120K(1056768K)], 0.0234567 secs]
|
||
```
|
||
|
||
**解读**:
|
||
- **GC**:Minor GC
|
||
- **Full GC**:Major GC
|
||
- **Allocation Failure**:新生代不足
|
||
- **Ergonomics**:自适应调整
|
||
- **2048K->512K(2560K)**:回收前 2048K,回收后 512K,总容量 2560K
|
||
- **0.0023456 secs**:停顿时间
|
||
|
||
---
|
||
|
||
### 7. 阿里 P7 加分项
|
||
|
||
**深度理解**:
|
||
- 理解 G1 的 Mixed GC 和 Region 设计
|
||
- 理解 ZGC 的染色指针和读屏障
|
||
- 理解 JVM 的 JIT 编译和逃逸分析
|
||
|
||
**实战经验**:
|
||
- 有处理线上 OOM 问题的经验
|
||
- 有 GC 参数调优的经验
|
||
- 有 GC 日志分析和优化经验
|
||
|
||
**架构能力**:
|
||
- 能设计高吞吐量或低延迟的 JVM 方案
|
||
- 能设计 JVM 监控和告警体系
|
||
- 能制定 JVM 调优规范
|
||
|
||
**技术选型**:
|
||
- 了解各种 GC 收集器的适用场景
|
||
- 了解 JDK 8/11/17/21 的 GC 改进
|
||
- 有 GraalVM 等新技术的使用经验
|