GC算法和种类

GC的概念

Garbage Collection 垃圾收集,简称GC。Java中GC的对象是堆空间和永久区。
复制代码

GC算法

引用计数法
  • 概念:引用计数法是老牌的垃圾回收算法了,经过对象的引用来计算要不要回收,com、ActionScript三、python 都使用过。
  • 原理:对于一个对象A,只要任何一个对象引用,则A的引用计数器就加1,若是取消引用就减一。若是计数器为零这个对象就是垃圾
  • 缺点:引用和去除引用伴随着加法减法,影响性能。还有就是很难处理循环引用(看下图)。
  • 优势:即时回收,由于对象知道本身何时没用
标记清除
  • 概念:标记——清除算法是现代垃圾回收算法的思想基础。
  • 原理:这个算法将垃圾回收分为了两个阶段,标记阶段和清除阶段。一种可行的实现是,在标记阶段,首先经过根节点,标记全部从根节点开始可达对象。所以未标记的对象就是未被引用的垃圾对象。而后在清除阶段,清除未被标记的对象。(看下图)
  • 缺点:逐渐产生被细化的分块,不久后就会致使无数的 小分块散布在堆的各处。这个内存就会被分的七零八落的,这样在分配对象的时候还得先遍历那些内存块能够用。
  • 优势:实现起来简单
标记压缩
  • 概念:标记-压缩算法适合用于存活对象较多的场合,如老年代。它在标记-清除算法的基础上作了一些优化
  • 原理:和标记清除同样,先标记可是以后清除操做的时候将全部存活的对象压缩到内存的一端,而后清理这个边界外的全部空间
  • 缺点:清除算法中,清除阶段也要搜索整个堆,不过搜索 1 次就够了。但 GC 标记 - 压缩算法要搜索 3 次,这样就要花费约 3 倍的时间,这是一个至关巨大的缺陷,特别是堆越 大,所消耗的成本也就越大(看图)
  • 优势:堆利用效率高。 并且 GC 标记 - 压缩算法不会出现 GC 复制算法那样只能利用半个堆的状况
复制算法
  • 概念:在标记清除的的基础上改进python

  • 原理:将原有的内存空间分为两块,每次只使用其中一块,在垃圾回收时,将正在使用的内存中的存活对象复制到未使用的内存块中,以后,清除正在使用的内存块中的全部对象,交换两个内存的角色,完成垃圾回收算法

  • 缺点:看图bash

  • 优势:ide

    一、优秀的吞吐量: GC 标记 - 清除算法消耗的吞吐量是搜索活动对象(标记阶段)所花费的时间和搜索总体 堆(清除阶段)所花费的时间之和。  
     另外一方面,由于 GC 复制算法只搜索并复制活动对象,因此跟通常的 GC 标记 - 清除算 法相比,它能在较短期内完成 GC。也就是说,其吞吐量优秀。
    
    二、高速分配:GC 复制算法不使用空闲链表。这是由于分块是一个连续的内存空间。比起 GC 标记 - 清除算法和引用计数法等使用空闲链表的分配,GC 复制算法明显快得多。
    
    三、不会发生碎片化
    复制代码
GC算法总结

总结的时候我以为仍是引入一下分代思想比较清晰post

依据对象的存活周期进行分类,短命对象归为新生代,长命对象归为老年代。性能

根据不一样代的特色,选取合适的收集算法优化

  • 少许对象存活,适合复制算法
  • 大量对象存活,适合标记清理或者标记压缩

可触及性

问:GC算法中 怎么判断这个对象是不是垃圾对象,是根据可触及性来判断的,那么什么是可触及性呢。ui

答:this

  • 栈中引用的对象
  • 方法区中静态成员或者常量引用的对象(全局对象)
  • JNI方法栈中引用对象

还有一个概念也不能断定这个对象是垃圾对象就是 --可复活的spa

一旦全部引用被释放,就是可复活状态,由于在finalize()中可能复活该对象
复制代码

不过这个通常不使用:

避免使用finalize(),操做不慎可能致使错误。
 优先级低,什么时候被调用, 不肯定
 什么时候发生GC不肯定
 可使用try-catch-finally来替代它经验:避免使用finalize(),操做不慎可能致使错误。 
 优先级低,什么时候被调用, 不肯定
 什么时候发生GC不肯定
 可使用try-catch-finally来替代它
复制代码

这里你能够代码试下

public class CanReliveObj {
   public static CanReliveObj obj;
   @Override
   protected void finalize() throws Throwable {
       super.finalize();
       System.out.println("CanReliveObj finalize called");
       obj=this;
   }
   @Override
   public String toString(){
       return "I am CanReliveObj";
   }


public static void main(String[] args) throws
    InterruptedException{
obj=new CanReliveObj();
obj=null;   //可复活
System.gc();
Thread.sleep(1000);
if(obj==null){
   System.out.println("obj 是 null");
}else{
   System.out.println("obj 可用");
}
System.out.println("第二次gc");
obj=null;    //不可复活
System.gc();
Thread.sleep(1000);
if(obj==null){
System.out.println("obj 是 null");
}else{
System.out.println("obj 可用");
}
}
复制代码

Stop-The-World

详情点击 juejin.im/post/5d5a1b…

Java中一种全局暂停的现象,全局停顿,全部Java代码中止,native代码能够执行,但不能和JVM交互,多半因为GC引发 Dump线程、 死锁检查、堆Dump。

GC时为何会有全局停顿? 类比在聚会时打扫房间,聚会时很乱,又有新的垃圾产生,房间永远打扫不干净,只有让你们中止活动了,才能将房间打扫干净。

危害:长时间服务中止,没有响应,遇到HA系统,可能引发主备切换,严重危害生产环境。

相关文章
相关标签/搜索