提纲:

🔥GC

  • 确认回收对象

  • 垃圾回收算法

  • 分代回收

  • 垃圾回收器

🎈面试八股真题

  • 1、如何判断对象可以被回收?

  • 2、JVM的永久代中会发生垃圾回收么?

  • 3、你知道哪些垃圾收集算法

  • 4、常见调优工具有哪些

  • 5、Minor GC与Full GC分别在什么时候发生?

  • 6、你知道哪些JVM性能调优参数?

  • 7、对象一定分配在堆中吗?有没有了解逃逸分析技术?

  • 8、如何选择垃圾收集器?

一、GC

1. 确认回收对象

  • 引用计数算法:为对象 A 准备一个引用计数器,每有一个对象 B 引用了 A,就为计数器 +1,每有一个引用失效时,-1,当计数为 0 时需要回收 # 当 A 与 B 互相引用会造成均无法回收

  • 可达性分析算法:先确认 GC Root 根对象,若从所有 root 对象开始搜索的引用链均无法到达对象,则需要回收

    • 根对象

      • 1、栈帧中本地变量表引用的对象

      • 2、本地方法栈引用的对象

      • 3、静态变量引用的对象

      • 4、方法区中常量引用的对象

    • 四种引用

      • 1、强引用:不会回收引用链上的强引用对象

      • 2、软引用:在垃圾回收后若内存仍然不足,对软引用对象进行第二次回收,继承 SoftReference 实现

      • 3、弱引用:在垃圾回收时进行回收,使类继承 WeakReference 即可实现 # 如 ThreadLocal 就继承自 WeakReference

      • 4、虚引用:回收对象后将虚引用放入引用队列,并在垃圾回收后由 Reference Handler 执行对应的方法 # 例如 ByteBuffer 中使用的 Cleaner,Cleaner 继承自 PhantomReference 虚引用,通过 create 方法将对象与一个回调接口进行绑定,最终由 Reference Handler 线程来执行这个回调方法进行资源的回收

2.垃圾回收算法

  • 标记清除

    • 原地的将需要回收的对象进行删除

    • 优点:效率高

    • 缺点:会产生大量内存碎片

  • 标记整理

    • 在标记清除过后,移动内存中剩下的对象来整理,让内存完全分为已使用和未使用的两块区域

    • 优点:没有内存碎片

    • 缺点:效率低,并且整理的过程中需要阻塞其他工作线程

  • 拷贝

    • 将内存分为大小相等的 From 区和 To 区,垃圾回收时将不需要回收的对象拷贝至 To 区,然后原地清空 From 区

    • 优点:效率高于标记整理且不会有内存碎片

    • 缺点:需要双倍的内存空间

3.分代回收

  • 新生代

    • 分为伊甸园区和幸存区,对象创建时分配在伊甸园区,若伊甸园区内存不足,触发一次新生代的 minor GC

    • 大对象会直接放入老年代,避免大对象在幸存区频繁拷贝

    • 在一次 minor GC 后存活的新生代对象会为对象头中分代年龄 age + 1,当 age > 15 时放入老年代

    • 空间分配担保:判断老年代是否够用的标准 #在进行 minor GC 前,JVM 需要检查老年代可用内存空间是否大于新生代对象总大小,若不满足,即担保失败,则可能造成新生代对象晋升至老年代失败;如果允许担保失败,会计算老年代剩余空间是否大于历次晋升的大小,若小于或不允许担保失败,就会触发 full GC

4.垃圾回收器

  • Serial:单线程的垃圾回收器,采用拷贝算法

  • Parnew:Serial 的多线程版,能与 CMS 搭配使用,可以通过配置修改最大回收线程数

  • Parallel Scavenge:并行的多线程垃圾回收器,关注吞吐量,即单次 STW 时间可能较长,但垃圾回收时间占程序运行总时间最少,适合不需要频繁网络交互的运算业务

  • Serial old:Serial 老年版,使用标记整理算法

  • Parallel old:并行老年版,搭配青春版使用追求最大吞吐量,采用标记整理算法

  • CMS:多线程的老年代垃圾回收器

    • 回收过程

      • 1、单次 STW,标记所有 root 可以直接到达的对象

      • 2、恢复工作线程,并发的标记垃圾回收对象

      • 3、并发标记期间,可能对象的引用状态发生了变化,再次 STW 进行重新标记

      • 4、并发清除,采用标记清除算***产生大量内存碎片

    • 缺陷

      • 1、CMS 默认启动的回收线程数是 (cpu + 3) / 4,对 cpu 资源敏感,虽然单次 STW 时间短,但在回收时会让程序运行变慢,使总吞吐量下降

      • 2、CMS 采用的是标记清除算***在老年代产生内存碎片,可能频繁触发 full GC

      • 3、在并发进行清除时,工作线程还会不断产生垃圾,也就是浮动垃圾,当 CMS 垃圾回收速度无法跟上浮动垃圾产生速度时,会导致并发失败,采用 Serial old 的方式回收,大大降低效率