【Java八股-第十一期】GC - Java基础
提纲:
🔥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 的方式回收,大大降低效率
-
4、为了应对浮动垃圾,需要在老年代预留出一部分空间,因而无法完全使用老年代,可以通过调整参数控制老年代最大使用,默认是 68%,若太大会造成预留空间不够,频繁的并发收集失败,若太小会造成实际老年代大小太小,就会频繁触发 full GC
-
-
-
G1 垃圾回收器
-
内存分配方式
-
1、仅是逻辑上将堆内存分为新生代和老年代,实际将整个堆内存划分为 2048 个独立的 Region,每一个Region 是一个连续的内存空间
-
2、将一部分 Region 用作新生代,一部分用作老年代,并使用特殊的 Region(Humongous) 专门存放大对象,如果一个 H 区也放不下,会寻找连续的 H 区尝试存储,如果还放不下,才会触发 full GC,总之就是比有大量内存碎片的 CMS 更好的处理了大对象的
-
-
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
【📫专栏目录在最底部📫】 - 本专栏适合于JAVA已经入门的学生或人士,有一定的编程基础。 - 本专栏特点: 本专刊囊括了JAVA、Spring、计算机网路、操作系统、计算机网络、MySQL、算法与数据结构、中间件等一系列知识点,总结出了高频面试考点(附有答案),事半功倍,为大家春秋招助力。 - 本专栏内容分为五章