zoukankan      html  css  js  c++  java
  • 垃圾收集器

    GC概念

      如果说垃圾收集算法是内存回收的方法论,那么垃圾收集器就是内存回收的具体实现。

      GC(Garbage Collection)的工作任务可以分为两类:内存的动态分配和垃圾回收。在内存执行分配之前,GC会先对内存进行划分区域,在上一篇博客中我们知道Java虚拟机使用了分代收集算法,所以堆区里面会被分为新生代和老年代两个区域,新生代又分为Eden空间、From空间和To空间。 空间划分完成后,GC就可以为新对象分配内存空间。

      在JDK版本这么多年发展的途中,垃圾收集器也已经出现了多种版本,基于分代的概念,不同的分代空间中活动着不同的GC。

      从不同的角度分析垃圾收集器,可以将GC分为不同的类型。

    按照线程数分,可分为串行垃圾回收器和并行垃圾回收器。
    按照工作模式分,可分为并发式垃圾回收器和独占式垃圾回收器。
    按碎片处理方式分,可分为压缩式垃圾回收器和非压缩式垃圾回收器。
    按工作内存分,可分为新生代垃圾回收器和老年代垃圾回收器。

    下面简单介绍这几个概念

    并发式回收器和独占式回收器

      并发式垃圾回收器与应用程序线程交替工作,以尽量减少程序的停顿时间。

      独占式回收器(Stop the world)一旦运行,就会停止应用程序中的其他所有线程,直到垃圾回收完全结束。

    串行回收器和并行回收器

      串行回收器是所有垃圾回收器中最古老的的一种,也是JDK中最基本的垃圾回收器之一,他的主要特点是使用单线程进行垃圾回收,其次,他是独占式的回收机制。

      串行回收是指在同一时间段内只允许一件事情发生,也就是说,当多个CPU可用时,也只能由一个CPU用于执行垃圾回收操作,并且在执行垃圾回收期间,其他的工作线程将被暂停,当垃圾回收完全结束之后才会恢复之前被暂停的工作线程。

      并行回收器是工作在新生代的垃圾收集器,它只是简单的将串行回收器多线程化,本质上和串行回收器一模一样。

      并行回收器也是独占式,在回收过程中,应用程序的线程会全部暂停,但是由于并行回收器使用多线程进行垃圾回收,在并发能力比较强的CPU上,它产生的停顿时间要短于串行回收器,而在单CPU系统中,并行回收器的效果不会比串行回收器好。

    压缩式回收器和非压缩式回收器

      压缩式垃圾回收器会在回收完成后,对存活对象进行压缩整理,消除回收后导致的内存空间碎片。

      没有整理空间碎片的步骤就叫非压缩回收器。

    Serial 收集器

      Serial收集器是历史最悠久的收集器,在早期的JKD版本中,Serial收集器是新生代唯一的选择。

      它是串行的,也是独占式的,这是它的缺点,但如果限定于单个CPU的环境来说,Serial收集器由于没有线程交互的开销,自然可以获得最高的单线程收集效率。

      注意:Serial收集器虽然古老,但是久经考验,在大多数情况下,性能表现是相当不错的,采用复制算法。

      同时,老年代中也有Serial收集器,叫做Serial Old收集器。

    ParNew 收集器

      ParNew收集器是一个工作在新生代的垃圾收集器,其实说白了就是Serial收集器的多线程版本,除了使用多线程进行垃圾收集之外,其他与Serial收集器相比并没有什么创新之处。

      ParNew收集器也是独占式,在收集过程中,应用程序的线程会全部暂停,但是由于并行收集器使用多线程进行垃圾回收,在并发能力比较强的CPU上,它产生的停顿时间要短于Serial收集器的。

      如果说ParNew收集器运行在多CPU的环境下,确实可以更快的完成垃圾收集。但是如果是在单个CPU的环境下,ParNew收集器是不如Serial高效的。

       ParNew收集器只存在于新生代中。

    Parallel 收集器

      Parallel收集器除了和ParNew收集器一样是基于并行回收以外,Parallel也同样的使用了复制算法和独占式机制。

      但是不同的是,Parallel收集器的关注点不同,它的关注点是系统的吞吐量,也被称作"吞吐量优先"的收集器。吞吐量 = 运行用户代码时间 / (运行用户代码时间 + 垃圾收集时间)

      需要注意的是,垃圾收集器中吞吐量和线程停顿时间是互相矛盾的,GC停顿时间缩短必须要牺牲吞吐量和新生代空间来换取,比如,系统把新生代调小一点,收集300M新生代肯定比收集500M新生代速度快,这也直接导致垃圾收集发生的更频繁,原来10秒收集一次,每次停顿100秒,现在变成5秒收集一次,每次停顿70秒,停顿时间下降了,但吞吐量也下降了。

      同样的,老年代中也存在Parallel收集器,叫做Parallel Old收集器。

    CMS 收集器

      CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器,它是一款优秀的老年代垃圾收集器。

      从名字可以看出,CMS为并发而生,并且使用的是标记清除算法。它的执行过程分为四个阶段:初始标记、并发标记、重新标记、并发清除。

      初始标记是独占式,但它速度很快,仅仅只是标记GC Roots所能关联到的对象,并发标记会将之前的不可达的所有对象标记为垃圾,由于在并发标记阶段有可能有些标记过的对象引用发生变动,为了解决这个问题,CMS会进入到重新标记阶段,经历过这三个阶段后,CMS最终进入到并发清除阶段执行内存回收。

      尽管CMS收集器采用的是并行回收,但是在初始标记阶段和重新标记阶段都使用的是独占式机制,需要暂停程序中的所有线程,可以说明目前所有的垃圾收集器都做不到完全不需要独占式机制,只是尽可能的缩短暂停时间而已。

      注意:CMS使用的算法是标记清除,因此清除垃圾后,会残留大量空间碎片。为了解决这个问题,MCS收集器会默认清除垃圾后进行碎片整理,也因此停顿时间不得不增长。

    G1 收集器

      G1(Garbage-First)收集器是当今收集器技术发展最前沿的成果之一,它解决了前三个收集器的很多缺陷。

      作为CMS的长期替代方案,G1使用了分代分区算法,特点如下:

    1.并行性:G1在回收期间,可以由多个GC线程同时工作,有效利用多核计算能力。
    2.并发性:G1拥有与应用程序交替执行的能力,部分工作可以和应用程序同时执行,因此一般来说,不会再整个回收期间完全阻塞应用程序。
    3.分代收集:G1和之前的回收器不同,它兼顾新生代和老年代,可以独立管理整个GC堆,能够采用不同的方式去管理新生代和老年代的对象。
    4.空间整理:G1是基于标记压缩算法实现的收集器,在每次回收后都会有效的整理空间。
    5.可预见性:由于分区的原因,G1可以只选取部分区域进行内存回收,这样缩小了回收范围,对于应用线程停顿可以有很好的控制。

    一切细节问题

    System.gc()

      在默认情况下,System.gc()会显示的触发Full GC,同时对老年代和新生代进行回收,一般情况下,垃圾回收应该是自动进行,不需要手动触发,如果过于频繁的触发垃圾回收对系统性能是没有好处的。

    对象进入老年代

      一般情况下,对象首次创建时,会被放置在新生代eden区,如果没有GC的介入,这些对象不会离开eden。

      两种情况下对象会进入老年代,第一种是对象经历的GC次数达到一定的值,默认为15次,就会进入老年代。第二种情况是对象的体积过大,也非常有可能会直接进入老年代。

  • 相关阅读:
    (转)学习笔记viewController(欢迎指错)
    配置Xcode版本控制SVN详细步骤内含解决Xcode/Mac OS10.8无法配置SVN的解决方法(转)
    iPhone 3G/3GS(有锁)基带与导航功能
    [转]Iphone 3G/3Gs Home键失灵的根本原因和解决方法
    NSDate的常用用法(转)
    短信操作(转)
    如何在Symbian SDK下使用GCCE4(转)
    nS60_sdk_v1_2的VC6问题(转)
    如何获取应用程序图标(转)
    如何实现圆角的UITextView iphone短信发送(非系统界面)
  • 原文地址:https://www.cnblogs.com/fengyumeng/p/10570257.html
Copyright © 2011-2022 走看看