提纲:
🔥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 的方式回收,大大降低效率
-
-