JVM知识点——垃圾回收

1、如何判断对象是否死亡?
①引用计数法:给对象中添加一个引用计数器,每当有一个地方引用它,计数器就加 1;当引用失效,计数器就减 1;任何时候计数器为 0 的对象就是不可能再被使用的。
特点:实现简单、效率高,但是无法解决对象之间相互循环引用的问题(A跟B相互引用,其他对象没有引用它们,因为它们互相引用所以计数器都不为0,回收不了)
②可达性分析算法:以一系列的“GC ROOTS”的对象作为起点,从这些节点开始往下搜索,节点走过的路径称为引用链,当一个对象到GC ROOTS没有任何引用链相连的话,则证明此对象是不可用的
JVM知识点——垃圾回收
2、被判定死亡的对象一定会被回收吗?
不一定,判定死亡的都对象会暂时处于“死缓阶段”,要先通过筛选,筛选的条件是此对象是否有必要执行finalize方法,当对象没有覆盖finalize或finalize方法已经被JVM调用过了,这两种情况将判定没必要finalize方法,因此对象会真正的死亡;当判定有必要执行finalize方法时,则下次垃圾回收时该对象会被回收,除非这个对象与引用链上任何一个对象建立关联
3、简单的介绍一下强引用、软引用、弱引用、虚引用
①强引用:类似于必不可少的生活用品,垃圾回收器绝不会回收它,当内存空间不足时,JVM宁愿抛出OOM错误
②软引用:类似可有可无的生活用品,如果内存空间足够,则不会回收它,如果空间不够,就会回收这些对象的内存。软引用可以和一个引用队列联合使用,如果软引用所引用的对象被垃圾回收,JAVA 虚拟机就会把这个软引用加入到与之关联的引用队列中。
③弱引用:类似可有可无的生活用品,一旦发现了仅持有弱引用的对象,不管内存空间是否足够,都会回收它的内存。弱引用可以和一个引用队列联合使用,如果弱引用所引用的对象被垃圾回收,Java 虚拟机就会把这个弱引用加入到与之关联的引用队列中。
④虚引用:顾名思义,就是形同虚设,一个对象仅持有虚引用,那么它就和没有任何引用一样,任何时候都可能被垃圾回收
4、虚引用与软引用和弱引用的区别
虚引用必须和引用队列联合使用。当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之关联的引用队列中。程序可以通过判断引用队列中是否已经加入了虚引用,来了解被引用的对象是否将要被垃圾回收。程序如果发现某个虚引用已经被加入到引用队列,那么就可以在所引用的对象的内存被回收之前采取必要的行动。
5、为什么相对弱引用、虚引用,软引用使用情况比较多?
因为软引用可以加速 JVM 对垃圾内存的回收速度,可以维护系统的运行安全,防止内存溢出(OutOfMemory)等问题的产生。
6、如何判断一个常量是废弃常量
假如在常量池中存在字符串 “abc”,如果当前没有任何 String 对象引用该字符串常量的话,就说明常量 “abc” 就是废弃常量,如果这时发生内存回收的话而且有必要的话,“abc” 就会被系统清理出常量池。
7、如何判断一个类是无用的类
需要满足三个条件
①该类所有的实例都已经被回收,也就是 Java 堆中不存在该类的任何实例。
②加载该类的 ClassLoader 已经被回收。
③该类对应的 java.lang.Class 对象没有在任何地方被引用,无法在任何地方通过反射访问该类的方法。
9、垃圾收集有哪些算法,各自的特点?
①标记-清除算法(最基础):首先标记出所有需要回收的对象,在标记完成后统一回收所有被标记的对象。这种垃圾收集算法会带来两个明显的问题:
1)效率问题
2)空间问题(标记清除后会产生大量不连续的碎片)
②复制算法:为了解决效率问题,复制算法出现了。将内存分为大小相同的两块,每次使用其中的一块。当这一块的内存使用完后,就将还存活的对象复制到另一块去,然后再把使用的空间一次清理掉。这样就使每次的内存回收都是对内存区间的一半进行回收
③标记-整理算法:标记过程仍然与“标记-清除”算法一样,但后续步骤不是直接对可回收对象回收,而是让所有存活的对象向一端移动,然后直接清理掉端边界以外的内存
④分代收集算法:根据各个年代的特点选择合适的垃圾手机算法。新生代中,每次收集都会有大量对象死去,所以可以选择复制算法,只需要付出少量对象的复制成本就可以完成每次垃圾收集。而老年代的对象存活几率是比较高的,而且没有额外的空间对它进行分配担保,所以我们必须选择“标记-清除”或“标记-整理”算法进行垃圾收集。
10、常见的垃圾回收器有哪些?
1)serial回收器:serial回收器是历史最悠久的垃圾回收器,它是一个单线程回收器,它单线程的意义不仅仅意味着只会使用一条垃圾回收线程去完成垃圾收集工作,更重要的是它进行垃圾回收工作时必须暂停其他所有的工作线程(即stop the world)直到收集结束。
算法:复制算法
特点是简单高效
2)ParNew回收器:parnew回收器其实就是 Serial 收集器的多线程版本,除了使用多线程进行垃圾收集外,其余行为(控制参数、收集算法、回收策略等等)和 Serial 收集器完全一样
算法:复制算法
补充:并发、并行的概念
并行:指多条垃圾收集线程并行工作,但此时用户线程仍然处于等待状态
并发:指用户线程与垃圾收集线程同时执行(但不一定是并行,可能会交替执行),用户程序在继续运行,而垃圾收集器运行在另一个 CPU 上
3)Parallel Scavenge 回收器:它跟parnew几乎一样,但parallel是吞吐量优先的收集器
算法:复制算法
4)Serial Old回收器:Serial 收集器的老年代版本,同样也是单线程的
算法:标记-整理
5)Parallel Old回收器:Parallel Old 是 Parallel 的老生代版本,同样是吞吐量优先的收集器
算法:标记-整理
6)CMS回收器:CMS(Concurrent Mark Sweep)一种以获得最短停顿时间为目标的收集器,非常适用B/S系统。它第一次它第一次实现了让垃圾收集线程与用户线程(基本上)同时工作。
算法:标记-清除
过程:
①初始标记:标记 GC Roots 直接关联的对象,需要 Stop The World 。
②并发标记:从 GC Roots 开始对堆进行可达性分析,找出活对象
③重新标记:为了修正并发标记期间因为用户程序继续运行而导致标记产生变动的那一部分对象的标记记录,这个阶段的停顿时间一般会比初始标记阶段的时间稍长,远远比并发标记阶段时间短,需要stop the world
④并发清除:清除垃圾对象
优点:并发收集、低停顿
缺点:对CPU资源敏感,无法处理浮动垃圾,会产生大量空间碎片
7)G1回收器:兼顾了吞吐量和停顿时间的回收器,是一款面向服务器的垃圾收集器,主要针对配备多颗处理器及大容量内存的机器. 以极高概率满足 GC 停顿时间要求的同时,还具备高吞吐量性能特征.
过程:初始标记、并发标记、最终标记、筛选回收
11、Minor Gc 和 Full GC 有什么不同呢?
新生代 GC(Minor GC):指发生新生代的的垃圾收集动作,Minor GC 非常频繁,回收速度一般也比较快。
老年代 GC(Major GC/Full GC):指发生在老年代的 GC,出现了 Major GC 经常会伴随至少一次的 Minor GC(并非绝对),Major GC 的速度一般会比 Minor GC 的慢 10 倍以上。