Java垃圾收集器

来源:互联网 发布:trpg知乎 编辑:程序博客网 时间:2024/06/04 23:33

今天第一天写博客,记录一下我的学习过程。

垃圾收集器(Carbage Collection,GC):

1.哪些垃圾需要垃圾收集器回收?

Java内存运行时,程序计数器、虚拟机栈、本地方法栈三个区域随线程生灭而存在或消失。而Java堆和方法区则不一样,一个接口中多个实现类需要的内存可能不一样,一个方法中多个分支需要的内存也不一样,只有在程序运行期间才能知道会创建哪些方法,所以这部分的内存分配和回收都是动态的,垃圾收集器所关注的就是这一部分。

2.什么时候回收?

  • 在堆里面存放着Java世界中几乎所有的对象实例,垃圾收集器在对堆进行回收前,第一件事就是要确定这些对象中哪些还“存活”着,哪些已经“死了”(不可能再被任何途径使用)。

  • 那么,如何判断对象是否存活?
    1> 给对象中添加一个引用计数器,每当有一个地方引用它时,计数器就加1,当引用实效时计数器值就减1,任何时刻计数器为0的对象就是不可能再被使用的。但是,其很难解决对象之间互相循环引用的问题,在主流的语言中废弃了。

    2> 可达性分析算法:通过一系列称为“GC Roots”的对象作为起点,从这个节点向下搜索,搜索走过的路径称为“引用链”。当对象到GC
    Roots没有任何引用链相连时,则证明这个对象是不可用的。

    这里写图片描述

    对象object5,object6,object7,虽然互相有关联,但是它们到GC Roots是不可达的,所以它们被判为可回收对象。

  • 无论是通过引用计数算法还是可达性分析法,判断对象的存活都与“引用”有关。JDK1.2之后,Java对引用分为强引用、软引用、弱引用、虚引用。这四种引用强度一次减弱。
    1> 强引用:类似于“Object obj = new Object()”这类普遍存在的引用。只要强引用还存在,垃圾收集器永远不会回收掉被引用对象。

    2> 软引用:用来描述还有用但并非必需的对象。被软引用关联的对象,在系统即将发生内存溢出异常之前,将会把这个对象列进回收范围之中进行二次回收。如果这次回收还没有足够内存,才会抛出内存溢出异常。在JDK1.2之后提供了SoftReference类来实现软引用。

    3> 弱引用:与软引用类似但比软引用更弱一些。被弱引用关联的对象,无论当时内存是否足够,都会回收掉被弱引用关联的对象。在JDK 1.2之后提供了WeakReference类来实现软引用。

    4> 虚引用:为一个对象设置虚引用的唯一目的就是能在这个对象被收集器回收时收到一个系统通知。在JDK 1.2之后提供了PhantomReference类来实现软引用。

  • 堆区中的每个对象都可能处于以下三个状态之一。
    1> 可触及状态:当一个对象(假定为A)被创建后,只要程序中还有引用变量引用它,那它就是可触及状态。
    2> 可复活状态:当发现GCRoots与A没有引用链相连后,它就进入可复活状态。在这个状态中,垃圾收集器会调用它的finalize()方法,这个方法,有可能使A对象重新转到可触及状态,并且这个方法只会被调用一次。
    3> 不可触及状态:当Java虚拟机执行完A的finalize()方法后,并且没有转到可触及状态,那么,A对象就进入不可触及状态。当对象进入不可触及状态就说明可以被回收了。

3.如何回收?

  • 垃圾收集算法:
    1> 标记-清除算法:首先标记出所有需要回收的对象,在标记完成后统一回收所有被标记的对象。
    缺点:①效率低,标记和清除效率都不高
    ②空间问题:标记清除后会产生大量的不连续空间碎片,导致以后需要分配较大对象时,不得不再触发一次垃圾收集动作。
    2> 复制算法:它将可用内存按容量划分为大小相等的两部分,每次只使用一部分。当一块用完了,就将还存活的对象复制到另一块,再把已使用过的清除掉。
    3> 分代收集算法:根据对象存活周期不同将内存划分为新生代和老年代。在新生代中,每次垃圾收集时都有大量对象死去,只有少量存活,就选用复制算法,而老年代中因为对象存活极高,必须使用 标记-清除算法 或者 标记-整理。
    新生代:初始对象,生命周期短的
    老年代:长时间存在的对象

    垃圾收集器:
    1> SerialNew收集器:是一个单线程收集器,针对新生代收集器,采用的是复制算法
    缺点:在收集垃圾时,必须暂停所有的工作线程。
    优点:简单而高效。没有线程交互的开销,分配给虚拟机管理的内存不是很大。
    2> ParaNew(并行)收集器:是Serial的多线程版本。新生代采用复制算法,老年代采用标记整理。
    3> Parallet Scavenge(并行)收集器:也是多并行的多线程收集器。针对新生代,采用复制算法。其目的是达到一个可控制的吞吐量。吞吐量=运行用户代码时间/(运行用户代码时间+垃圾手机时间),虚拟机总共运行了100分钟,其中垃圾收集花掉了1分钟,那吞吐量就是99%。
    4> CMS收集器:是一种以获取最短停顿时间为目的收集器,基于标记清理。
    优点:并发收集;低停顿。
    缺点:①对CPU资源非常敏感,导致应用程序变慢,总吞吐量变低。
    ②无法处理浮动垃圾
    ③会产生大量空间碎片
    5> G1收集器:面向服务端的垃圾收集器。
    优点:①并发且并行
    ②分代收集
    ③空间整合
    ④可预测的停顿

原创粉丝点击