Java 垃圾回收机制
TIP
Java 的垃圾回收(GC)自动管理内存,开发者无需手动释放对象。了解 GC 机制有助于写出更高效的程序。
对象存活判定
引用计数法(主流 JVM 不采用)
无法解决循环引用问题。
可达性分析算法(主流)
从 GC Roots 出发,不可达的对象即为可回收对象。
垃圾回收算法
| 算法 | 描述 | 优缺点 |
|---|---|---|
| 标记-清除 | 标记后直接清除 | 产生内存碎片 |
| 复制 | 将存活对象复制到另一区域 | 无碎片,浪费空间 |
| 标记-整理 | 标记后整理到一端 | 无碎片,效率较低 |
| 分代收集 | 不同代用不同算法 | 综合各种优点 |
分代回收
java
// JDK8 默认 GC 组合
// 新生代:ParNew(复制算法)
// 老年代:CMS(标记-清除)或 Parallel Old(标记-整理)
// 对象分配规则
// 1. 优先在 Eden 分配
// 2. 大对象直接进入老年代(-XX:PretenureSizeThreshold)
// 3. 长期存活进入老年代(-XX:MaxTenuringThreshold=15)常用的垃圾回收器
java
// 串行(-XX:+UseSerialGC)
// 适合单核、小内存,暂停时间较长
// 并行(-XX:+UseParallelGC)
// 吞吐量优先,适合后台计算任务
// CMS(-XX:+UseConcMarkSinkMC)
// 低延迟,适合响应式服务,但会产生碎片
// G1(-XX:+UseG1GC)JDK9 默认
// 可预测停顿时间,适合大堆内存GC 调优参数
bash
# 常用 GC 调优参数
-Xms4g -Xmx4g # 堆大小
-Xmn2g # 新生代大小
-XX:MetaspaceSize=256m # 元空间初始大小
-XX:+UseG1GC # 使用G1回收器
-XX:MaxGCPauseMillis=100 # 目标最大停顿时间
-XX:+PrintGCDetails # 打印GC详情
-XX:+HeapDumpOnOutOfMemoryError # OOM时导出堆转储常见的 OOM 场景
java
// 1. 堆溢出 - Java heap space
// 原因:对象无法分配到堆内存
// 2. 栈溢出 - StackOverflowError
// 原因:方法调用层级过深(递归无终止条件)
// 3. 元空间溢出 - Metaspace
// 原因:加载了过多类(如动态代理滥用)TIP
GC 调优的目标通常是在满足停顿时间要求的前提下,提高吞吐量。建议先明确问题(吞吐量低?响应慢?),再针对性调整参数。