详解GC收集算法
更多干货
一、引用计数算法
给对象中添加一个引用计数器、每当有一个地方引用它时、计数器值就加1;当引用失效时,计数器就减1;任何计数器为0的对象就是不可能再被使用的。
二、可达性分析算法
判断一个对象是否可以被垃圾回收,这个算法的基本思路是通过一系列的称谓“GC Roots”的对象作为起始点,从这些节点开始向下搜索,搜索所有走过的路径称为引用链,当一个对象到GC Roots没有任何引用链相连,则说明该对象是不可用的。
三、可作为GC Roots对象的有
- 虚拟机栈(栈中的本地变量表)中引用的对象
- 方法区中类静态属性引用的对象
- 方法区中常量引用的对象
- 本地方法栈中JNI(即Native方法)引用的对象
四、对象引用类型
- 强引用:使用new 关键字创建的引用,只要强引用还存在,则垃圾回收永远不会回收掉被引用的对象
- 软引用:描述还有用但是非必须的对象,在系统即将发生内存溢出的时候才将这些对象放到回收范围中进行二次回收,如果回收之后还没有足够内存,则出现内存溢出异常
- 弱引用:用来描述非必须的对象,但是它比软引用要弱一些,当垃圾回收期工作时,无论内存是否够用都会将引用的对象回收掉
- 虚引用:它是最弱的一种引用关系,对象是否有虚引用不会影响其生命周期,虚引用的唯一目的就是能在这个对象被回收是收到一个系统通知
五、finalize()方法;
对象在被回收之前要经历两次被标记过程,如果发现对象经可达性分析检测,没有引用关联,它将会被标记并且进行筛选,筛选条件是此对象是否有必要执行finalize()方法,当对象没有覆盖finalize()方法或finalize()方法已被虚拟机调用过,虚拟机认为这两种情况均为没有必要执行,对象将被回收,反之先执行finalize()后,收集对象,JVM并不保证finalize()一定成功被执行。
六、GC收集算法:
- 标记-清除算法:标记所有需要回收的对象,然后依次全部清除。但是有不足,一是效率问题,标记和清除两个过程效率都不是很高,二是空间问题会产生很多碎片,对于大对象无法分配空间
- 复制算法:将内存分为大小相等的两块,每次用一块,当一块内存用问了,将存货的对象移动到另一块,然后将本快内存全部清除
- 标记-整理算法:让多有存活的对象向一端移动,然后清理掉边界以外的空间。
- 分代收集算法:分为新生代和老年代,新生代堆已死对象进行清除,少量存活的对象迁移到老年代。然后老年代才用标记-清除算法或者标记-整理算法进行清理。
七、垃圾收集器
HotSpotJVM收集器,其中收集器,分为两块,上面为新生代收集器,下面是老年代收集器。如果两个收集器之间存在连线,就说明他们可以搭配使用
1、Serial(串行GC)收集器
Serial收集器是一个新生代收集器,单线程执行,使用复制算法。它在进行垃圾收集时,必须暂停其他所有的工作线程(用户线程)。是Jvm client 模式下默认的新生代收集器。对于限定单个CPU的环境来说,Serial收集器由于没有线程交互的开销,专心做垃圾收集自然可以获得最高的单线程收集效率
2、ParNew(并行GC)收集器
ParNew 收集器其实就是Serial收集器的多线程版本,除了使用多条线程进行垃圾收集之外,其余行为与Serial收集器一样。
3、ParallelScavenge收集器
是一个新生代收集器,它也是使用复制算法的收集器,又是并行多线程收集器。Parallel Scavenge 收集器的特点是它的关注点与其他收集器不同, CMS等收集器的关注点是尽可能的缩短垃圾收集时用户线程的停顿时间,而Parallel Scavenge收集器的目标是达到一个可控制的吞吐量。 吞吐量=程序运行时间/(程序运行时间+垃圾收集时间)、虚拟机总共运行了100分钟。其中垃圾收集花掉1分钟,那吞吐量就是99%
4、SerialOld (串行GC)收集器
Serial Old是Serial收集器的老年代版本,它同样使用一个单线程执行收集、使用“标记-整理”算法。主要使用在Client模式下的虚拟机。
5、ParallelOld(并行GC)收集器
Serial Old是Parallel Scavenge收集器的老年代版本,使用多线程和“标记-整理”算法