美文网首页java road
Java的垃圾回收机制-学习笔记

Java的垃圾回收机制-学习笔记

作者: HardWJJ | 来源:发表于2018-06-22 13:53 被阅读23次

    可回收对象的判定方法:

    引用计数法:

    对于一个对象 A,只要有任何一个对象引用了 A,则 A 的引用计数器就加 1,当引用失效时,引用计数器就减 1。只要对象 A 的引用计数器的值为 0,则对象 A 就不可能再被使用。

    • 缺点:循环引用,可能导致内存泄漏

    可达性分析法:

    • 可作为可达性分析法的GC Roots
      1、在虚拟机栈(栈帧中的本地变量表)中引用的对象。
      2、在方法区中的类静态属性引用的对象。
      3、在方法区中的常量引用的对象。
      4、在本地方法栈中JNI(Nativate方法)的引用对象。
    • 优点:解决引用计数法的循环引用问题

    常见的GC算法:

    标记-清除算法(Mark-Sweep):

    基础的GC算法,主要的步骤为标记和清除。

    • 一种可行的实现是,在标记阶段首先通过根节点,标记所有从根节点开始的较大对象。因此,未被标记的对象就是未被引用的垃圾对象。然后,在清除阶段,清除所有未被标记的对象。

    • 缺点:这个算法效率不高,清理完成后会产生内存碎片,如果有大对象需要连续的内存空间时,还需要进行碎片整理。

      复制算法(Copying):

    将现有的内存空间分为两快,每次只使用其中一块,在垃圾回收时将正在使用的内存中的存活对象复制到未被使用的内存块中,之后,清除正在使用的内存块中的所有对象,交换两个内存的角色,完成垃圾回收。

    • 优点:
      1、 如果系统中的垃圾对象很多,复制算法需要复制的存活对象数量并不会太大。因此在真正需要垃圾回收的时刻,复制算法的效率是很高的。
      2、可确保回收后的内存空间是没有碎片的。
    • 缺点:
      1、该算法的缺点是将系统内存折半。
    • 使用场景:
      1、Java 的新生代串行垃圾回收器中使用了复制算法的思想。

    标记-整理(或叫压缩)算法(Mark-Compact):

    标记-压缩算法是一种老年代的回收算法。首先需要从根节点开始对所有可达对象做一次标记,但之后,它并不简单地清理未标记的对象,而是将所有的存活对象压缩到内存的一端。

    • 优点:
      1、标记-清除算法的基础上做了一些优化。
      2、不需要两块相同的内存空间,因此,其性价比比较高。
      3、解决老年代中大对象使用复制算法成本较高的问题。
    • 使用场景:
      1、Java 的老年代。

    增量算法 (Incremental Collecting):

    增量算法的基本思想是,让垃圾收集线程和应用程序线程交替执行。每次,垃圾收集线程只收集一小片区域的内存空间,接着切换到应用程序线程。依次反复,直到垃圾收集完成。

    • 优点:
      1、在垃圾回收过程中,间断性地还执行了应用程序代码,所以能减少系统的停顿时间。
    • 缺点:
      1、由于应用程序线程与垃圾收集线程之前频繁切换,会使得垃圾回收的总体成本上升,造成系统吞吐量的下降。

    分代算法 (Generational Collecting):

    将内存区间根据对象的特点分成几块,根据每块内存区间的特点,使用不同的回收算法,以提高垃圾回收的效率。

    • 以 Hot Spot 虚拟机为例,它将所有的新建对象都放入称为年轻代的内存区域,在年轻代就选择效率较高的复制算法。在老生代中,根据分代的思想,可以对老年代的回收使用与新生代不同的标记-压缩算法,以提高垃圾回收效率。

    常见的垃圾收集器:

    新生代串行收集器:

    新生代串行处理器使用复制算法,实现相对简单,逻辑处理特别高效,且没有线程切换的开销。
    两个特点:
    第一,它仅仅使用单线程进行垃圾回收。
    第二,它独占式的垃圾回收。

    • 优点:
      1、在单 CPU 处理器或者较小的应用内存等硬件平台不是特别优越的场合,它的性能表现可以超过并行回收器和并发回收器。
    • 使用场景:
      1、当 JVM 在 Client 模式下运行时,它是默认的垃圾收集器。
    • 在 HotSpot 虚拟机中,可以使用-XX:+UseSerialGC 参数指定。

    老年代串行收集器:

    使用的是标记-压缩算法。和新生代串行收集器一样,它也是一个串行的、独占式的垃圾回收器。

    • 缺点:
      1、在堆空间较大的应用程序中,一旦老年代串行收集器启动,应用程序很可能会因此停顿几秒甚至更长时间。
    • 在 HotSpot 虚拟机中,可以使用-XX:+UseSerialGC 参数指定。
    • -XX:+UseParNewGC 参数设置,表示新生代使用并行收集器,老年代使用串行收集器。

    并行收集器(ParNew):

    工作在新生代的垃圾收集器,它只简单地将串行回收器多线程化。它的回收策略、算法以及参数和串行回收器一样。

    • 优点:
      1、加入了多线程机制,提高了效率。
    • 缺点:
      1、在单 CPU 或者并发能力较弱的系统中,由于多线程的压力,它的实际表现很可能比串行回收器差。
    • 使用场景:
      1、被用在服务器端(Server)上。
      2、可以与CMS GC配合使用。
    • 使用参数-XX:+UseParNewGC,该参数设置新生代使用并行收集器,老年代使用串行收集器。
    • 使用参数-XX:+UseConcMarkSweepGC 可以要求新生代使用并行收集器,老年代使用 CMS。
    • 使用参数-XX:ParallelGCThreads指定并行收集器工作时的线程数量。

    新生代并行回收收集器(Parallel Scavenge):

    和并行收集器一样都是多线程、独占式的收集器。
    特点:它非常关注系统的吞吐量。

    • 使用场景:
      1、server级别默认采用的GC方式。
    • 使用参数
      1、-XX:+MaxGCPauseMills指定最大垃圾收集停顿时间。
      2、-XX:+UseParallelGC:新生代使用并行回收收集器,老年代使用串行收集器。
      3、-XX:+UseParallelOldGC:新生代和老年代都是用并行回收收集器。
      4、-XX:ParallelGCThreads指定线程数。
      5、-XX:+GCTimeRatio指定吞吐量大小。
      6、-XX:+UseAdaptiveSizePolicy 可以打开自适应 GC 策略。

    老年代并行回收收集器:

    多线程并发的收集器,关注吞吐量的收集器。JDK1.6 之后开始使用标记-压缩算法。

    • 使用参数
      1、-XX:+UseParallelOldGC 可以在新生代和老生代都使用并行回收收集器。
      2、-XX:ParallelGCThreads指定线程数。

    CMS (Concurrent Mark Sweep):

    主要关注于系统停顿时间,使用的是标记-清除算法,是一个使用多线程并发回收的垃圾收集器。

    • 为解决Serial GC 的停顿问题,以达到最短回收时间。基于“标记-清除”算法实现的,整个收集过程大致分为4个步骤:
      1、初始标记(CMS initial mark)
      2、并发标记(CMS concurrenr mark)
      3、重新标记(CMS remark)
      4、并发清除(CMS concurrent sweep)
    • 初始标记仅仅只是标记出GC ROOTS能直接关联到的对象,速度很快,并发标记阶段是进行GC ROOTS 根搜索算法阶段,会判定对象是否存活。而重新标记阶段则是为了修正并发标记期间,因用户程序继续运行而导致标记产生变动的那一部分对象的标记记录。CMS收集器的内存回收过程是与用户线程一起并发执行的。
    • 优点:
      1、并发收集
      2、低停顿。
    • 缺点:
      1、在并发阶段,会占用CPU资源而导致引用程序变慢,总吞吐量下降。
      2、无法清除由于CMS并发清理阶段用户线程产生的垃圾。
      3、需要预留足够的内存空间给用户线程使用。
      4、使用“标记-清除”算法收集后,会产生大量碎片。在分配大对象时,内存空间找不到连续的空间来分配不得不提前触发一次Full GC。
    • 使用参数:
      1、-XX:CMSInitiatingOccupancyFraction的值来提供老年代使用空间的触发百分比。
      2、-XX:ParallelCMSThreads 参数手工设定 CMS 的线程数量。
      3、使用-XX:CMSInitiatingOccupancyFraction 来指定,默认是 68。即当老年代的空间使用率达到 68%时,会执行一次 CMS 回收。如果内存增长缓慢,则可以设置一个稍大的值,大的阈值可以有效降低 CMS 的触发频率,减少老年代回收的次数可以较为明显地改善应用程序性能。如果应用程序内存使用率增长很快,则应该降低这个阈值。
      3、-XX:+UseCMSCompactAtFullCollection 参数可以使 CMS 在垃圾收集完成后,进行一次内存碎片整理。
      4、-XX:CMSFullGCsBeforeCompaction 参数可以用于设定进行多少次 CMS 回收后,进行一次内存压缩。

    G1收集器:

    一款服务器的垃圾收集器,在吞吐量和停顿控制上,预期要优于 CMS 收集器。

    • 优点:
      1、不会产生空间碎片,没有必要在收集完成后,进行一次独占式的碎片整理工作。
      2、进行非常精确的停顿控制。
    • 使用参数:
      1、-XX:MaxGCPauseMills=20,-XX:GCPauseIntervalMills=200:设置 G1 回收器的目标停顿时间。
      2、-XX:+UnlockExperimentalVMOptions –XX:+UseG1GC 来启用 G1 回收器

    参考资料:

    1、Java之美[从菜鸟到高手演变]之JVM内存管理及垃圾回收 - CSDN博客
    2、JVM 自动内存管理:对象判定和回收算法-极客学院
    3、Java 技术,IBM 风格: 垃圾收集策略,第 1 部分
    4、JVM 垃圾回收器工作原理及使用实例介绍

    相关文章

      网友评论

        本文标题:Java的垃圾回收机制-学习笔记

        本文链接:https://www.haomeiwen.com/subject/ldhoeftx.html