zoukankan      html  css  js  c++  java
  • JVM的GC概述

    JVMGC概述

    GC即垃圾回收,是指jvm用于释放那些不再使用的对象所占用的内存。
    在充分理解了垃圾收集算法和执行过程后,才能有效的优化它的性能。

    有些垃圾收集专用于特殊的应用程序。比如,实时应用程序主要是为了避免垃圾收集中断,而大多数OLTP应用程序则注重整体效率。
    垃圾收集的目的在于清除不再使用的对象。gc通过确定对象是否被活动对象引用来确定是否收集该对象。两种常用的方法是引用计数和对象引用遍历。
    引用计数
    引用计数存储对特定对象的所有引用数,也就是说,当应用程序创建引用以及引用超出范围时,jvm必须适当增减引用数。当某对象的引用数为0时,便可以进行垃圾收集。
    对象引用遍历
    早期的jvm使用引用计数,现在大多数jvm采用对象引用遍历。对象引用遍历从一组对象开始,沿着整个对象图上的每条链接,递归确定可到达(reachable)的对象。如果某对象不能从这些根对象的一个(至少一个)到达,则将它作为垃圾收集。在对象遍历阶段,gc必须记住哪些对象可以到达,以便删除不可到达的对象,这称为标记(marking)对象。

     

    基本的回收算法:

    空间维度:标记-清除、标记-压缩、标记-复制、增量回收、分代回收

    时间维度:串行回收、并发回收、并行回收

     

    标记-清除:

    标记清除的算法最简单,主要是标记出来需要回收的对象,然后然后把这些对象在内存的信息清除,会产生大量内存碎片。

     

     

     

    标记-压缩

    有时也叫标记-清除-压缩收集器,这个算法是在标记-清除的算法之上进行剪切操作,将存活对象压缩在一起,减少内存碎片。由于压缩空间需要一定的时间,会影响垃圾收集的时间。

     

    标记-复制

     

    这个算法是把内存分配为两个空间,一个空间(A)用来负责装载正常的对象信息,另外一个内存空间(B)是垃圾回收用的。

    每次把空间A中存活的对象全部复制到空间B里面,在一次性的把空间A删除。

    这个算法在效率上比标记-清除-压缩高,但是需要两块空间,对内存要求比较大,内存的利用率比较低。适用于短生存期的对象,持续复制长生存期的对象则导致效率降低。

     

     

     

    增量回收:

    增量回收器:把堆分为多个域,每次对从一个域进行垃圾回收。这样只会早点一小部分程序暂停。

    分代回收:

    基于对对象生命周期分析后得出的垃圾回收算法。把对象分为年青代、年老代、持久代,对不同生命周期的对象使用不同的算法进行回收。

     

    串行回收:

    用单线程处理所有垃圾回收工作,因为无需多线程交互,所以效率比较高。但是,也无法使用多处理器的优势,所以此收集器适合单处理器机器

     

     

    并行回收:

    用多线程处理所有垃圾回收工作,利用多核处理器的优势。对于空间不大的区域(如young generation),采用并行收集器停顿时间很短,回收效率高,适合高频率执行。但是如果线程数量过多,导致线程之间频繁调度,也会影响性能。一半并行收集的线程是处理器的个数。

     

     

    并发回收:

    并发收集器GC时GC线程和应用线程大部分时间是并发执行,只是在初始标记(initial mark)和二次标记(remark)时需要stop-the-world,这可以大大缩短停顿时间(pause time),所以适用于响应时间优先的应用,减少用户等待时间。由于GC是和应用线程并发执行,只有在多CPU场景下才能发挥其价值,在一个N个处理器的系统上,并发收集部分使用K/N个可用处理器进行回收,一般情况下1<=K<=N/4。在执行过程中还会产生新的垃圾floating garbage(浮动垃圾),如果等空间满了再开始GC,那这些新产生的垃圾就没地方放了(并发收集器一般需要20%的预留空间用于这些浮动垃圾),这时就会启动一次串行GC,等待时间将会很长,所以要在空间还未满时就要启动GC。mark和sweep操作会引起很多碎片,所以间隔一段时间需要整理整个空间,否则遇到大对象,没有连续空间也会启动一次串行GC。采用此收集器,收集频率不能大,否则会影响到cpu的利用率,进而影响吞吐量。

     

     

    JVMGC触发原理

    JVM的GC主要是对堆内存的回收,

    一般把新生代的GC称为minor GC ,把老年代的GC成为 full GC,所谓full gc会先出发一次minor gc,然后在进行老年代的GC。

    首先想eden区申请分配空间,如果空间够,就直接进行分配,否则进行一次Minor GC。

    minor GC 首先会对Eden区的对象进行标记,标记出来存活的对象。然后把存活的对象copy到From空间。

    如果From空间足够,则回收eden区可回收的对象。

    如果from内存空间不够,则把From空间存活的对象复制到To区,

    如果TO区的内存空间也不够的话,则把To区存活的对象复制到老年代。

    如果老年代空间也不够(或者达到触发老年年垃圾回收条件的话)则触发一次full GC。

    简单方向就是Eden->From->To->Old,如下图所示:

     

     

    默认是不会对持久带(方法区)进行垃圾回收的,设置参数可回收:-XX:+CMSClassUnloadingEnabled

     

    JVM支持的GC收集器

    JVM采用的是分代回收,不同代有不同的垃圾收集器

    如图所示:连线的是可以组合使用

     

     

    各个收集器的细节我就不在这里COPY/PASTE了,SerialOld收集器在书的图中没有,是我后加上的,其实很少使用。

     

  • 相关阅读:
    Codeforces Round #251 (Div. 2) A
    topcoder SRM 623 DIV2 CatAndRat
    topcoder SRM 623 DIV2 CatchTheBeatEasy
    topcoder SRM 622 DIV2 FibonacciDiv2
    topcoder SRM 622 DIV2 BoxesDiv2
    Leetcode Linked List Cycle II
    leetcode Linked List Cycle
    Leetcode Search Insert Position
    关于vim插件
    Codeforces Round #248 (Div. 2) B. Kuriyama Mirai's Stones
  • 原文地址:https://www.cnblogs.com/metoy/p/3703128.html
Copyright © 2011-2022 走看看