跳到主要内容

图解Jvm 12.垃圾回收相关概念

·1778 字·4 分钟

1. System.gc()的理解 #

工作机制图解 #

核心要点 #

  1. 非强制调用<font style="background-color:rgb(252, 252, 252);">System.gc()</font>本质是<font style="background-color:rgb(252, 252, 252);">Runtime.getRuntime().gc()</font>的封装,只是建议而非强制
  2. 执行不确定性
    • 可能触发Full GC(YoungGC+OldGC+MetaspaceGC)
    • 具体行为取决于<font style="background-color:rgb(252, 252, 252);">-XX:+ExplicitGCInvokesConcurrent</font>参数
  3. 生产环境禁用建议
-XX:+DisableExplicitGC  # 禁止显式GC调用
-XX:+ExplicitGCInvokesConcurrent  # 使用并发方式执行

2. 内存溢出与内存泄露 #

内存溢出(OOM)图解 #

常见OOM类型 #

  1. Heap OOM<font style="background-color:rgb(252, 252, 252);">Java heap space</font>
  2. Metaspace OOM<font style="background-color:rgb(252, 252, 252);">Metaspace</font>
  3. 栈OOM<font style="background-color:rgb(252, 252, 252);">Requested stack size exceeded</font>
  4. 直接内存OOM<font style="background-color:rgb(252, 252, 252);">Direct buffer memory</font>

内存泄漏(Memory Leak)案例 #

public class MemoryLeak {
    static List<Object> list = new ArrayList<>();

    public void addData() {
        for(int i=0; i<1000; i++){
            list.add(new byte[1024 * 1024]); // 持续添加大对象
        }
    }
}

泄漏特征 #

  1. 对象不再使用但仍被GC Roots引用
  2. 常见泄漏场景:
    • 静态集合类
    • 未关闭的资源(数据库连接、文件流)
    • 监听器未注销

3. Stop The World #

STW发生机制图解 #

关键影响与优化 #

  1. 暂停时间指标
    • CMS:<font style="background-color:rgb(252, 252, 252);">-XX:MaxGCPauseMillis=200</font>(默认200ms)
    • G1:<font style="background-color:rgb(252, 252, 252);">-XX:MaxGCPauseMillis=200</font>
  2. 优化策略
-XX:+UseParallelGC       # 并行回收缩短STW
-XX:+UseConcMarkSweepGC  # CMS并发标记
-XX:+UseG1GC             # G1的可预测暂停

4. 垃圾回收的并行与并发 #

概念对比图解 #

技术实现细节 #

  1. 并行(Parallel)

- <font style="color:rgba(0, 0, 0, 0.9);background-color:rgb(252, 252, 252);">典型场景:</font>`<font style="background-color:rgb(252, 252, 252);">-XX:+UseParallelGC</font>`<font style="color:rgba(0, 0, 0, 0.9);background-color:rgb(252, 252, 252);">(ParNew/Parallel Scavenge)</font>
  1. 并发(Concurrent)

- <font style="color:rgba(0, 0, 0, 0.9);background-color:rgb(252, 252, 252);">典型场景:CMS的并发标记阶段</font>

5. 安全点与安全区域 #

安全点(Safepoint)机制 #

主动式中断实现 #

// HotSpot虚拟机源码片段
void SafepointSynchronize::block_jni_calls() {
    while (true) {
        if (SafepointSynchronize::is_synchronized() break;
        os::naked_short_sleep(1);  // 自旋等待
    }
}

安全区域(Safe Region) #


6. 再谈引用:强引用 #

强引用生命周期 #

典型代码示例 #

Object obj = new Object();  // 强引用
obj = null;  // 断开引用后对象可被回收

强引用与内存泄漏 #

7. 再谈引用:软引用 #

回收机制图解 #

典型使用场景 #

// 创建软引用对象
SoftReference<byte[]> softRef = new SoftReference<>(new byte[10 * 1024 * 1024]);

// 获取对象(可能返回null)
byte[] data = softRef.get(); 
if(data == null) {
    // 重新加载数据
}

参数调优 #

-XX:SoftRefLRUPolicyMSPerMB=1000  # 每MB空闲内存保留软引用1秒

8. 再谈引用:弱引用 #

生命周期图解 #

WeakHashMap应用 #

WeakHashMap<Key, Value> cache = new WeakHashMap<>();
Key key = new Key();
cache.put(key, new Value();

key = null;  // 下次GC时自动清理条目

9. 再谈引用:虚引用 #

对象跟踪机制 #

典型应用场景 #

// 创建虚引用(必须关联引用队列)
PhantomReference<Object> phantomRef = new PhantomReference<>(new Object(), queue);

// 监控对象回收(常用于堆外内存管理)
while(true) {
    Reference<?> ref = queue.remove();
    // 执行内存回收后续操作
}

10. 终结器引用 #

finalize()执行流程 #

代码警示案例 #

public class Zombie {
    static Zombie saved;

    @Override
    protected void finalize() {
        saved = this; // 对象复活
    }
}

11. 常见问题与解决方案 #

内存泄漏排查工具链 #

MAT分析步骤 #

  1. 生成堆转储文件
jmap -dump:format=b,file=heap.bin <pid>
  1. 查看支配树(Dominator Tree)
  2. 分析对象引用链

12. 高频面试问题与解答 #

问题1:System.gc()一定会触发GC吗? #

:不一定。取决于JVM实现和运行参数,使用<font style="background-color:rgb(252, 252, 252);">-XX:+DisableExplicitGC</font>会完全禁用该调用。

问题2:内存泄漏和内存溢出的区别? #

  • 内存泄漏:对象不再使用但无法回收(长期积累导致OOM)
  • 内存溢出:当前内存空间无法满足分配需求(可能瞬时发生)

问题3:如何减少STW时间? #

  1. 使用G1/CMS等低延迟收集器
  2. 调整堆大小:<font style="background-color:rgb(252, 252, 252);">-Xmx4g -Xms4g</font>
  3. 控制年轻代比例:<font style="background-color:rgb(252, 252, 252);">-XX:NewRatio=2</font>

问题4:弱引用和软引用的核心区别? #

  • 软引用:内存不足时回收(适合缓存)
  • 弱引用:发现即回收(适合辅助数据结构)

问题5:安全点如何影响GC性能? #

  • 安全点过少 → STW等待时间增加
  • 安全点过多 → 运行时性能损耗
  • 优化方向:<font style="background-color:rgb(252, 252, 252);">-XX:GuaranteedSafepointInterval=30000</font>

总结图谱 #