JVM的GC概述

JVMGC概述算法

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

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

 

基本的回收算法:jvm

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

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

 

标记-清除:spa

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

 

 

 

标记-压缩3d

有时也叫标记-清除-压缩收集器,这个算法是在标记-清除的算法之上进行剪切操做,将存活对象压缩在一块儿,减小内存碎片。因为压缩空间须要必定的时间,会影响垃圾收集的时间。对象

 

标记-复制

 

这个算法是把内存分配为两个空间,一个空间(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收集器在书的图中没有,是我后加上的,其实不多使用。

相关文章
相关标签/搜索