JVM之GC收集器

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/carson0408/article/details/83503815

        JVM中GC垃圾回收机制与垃圾回收算法一文中已经介绍了垃圾回收机制以及对应的一些回收算法,本文主要更深入了解JVM中的GC机制以及不同GC收集器的工作功用以及优缺点。

         首先,GC的主要区域是堆,而堆主要划分为新生代和老生代。其中新生代主要划分为eden、survivor0、survivor1三个区域,且内存比例为8:1:1.

                       

1.新生代可用GC

a.串行GC(Serial GC):新生代分配内存采用的为空闲指针的方式。基于Copying算法,需要从根集合扫描出存活的对象。根集合对象:当前运行线程的栈上引用的对象、常量及静态变量、传到本地方法中,还没有被本地方法释放的对象引用。由于是串行工作,所以进行垃圾回收时,必须暂停其它所有的工作线程,这会导致GC时间比较长。

注:JDK采用了remember set解决旧生代中的对象引用了新生代的对象的问题。JDK在进行对象赋值时,如果赋值的为一个对象引用,则产生write barrier,然后检查需要赋值的对象是否在旧生代及赋值的对象是否引用新生代,如果满足,则在remenber set做个标记,JDK采用了Card Table来实现remeber set。

b.并行回收GC(Parallel Scavenge):需要配置SurvivorRatio来分配Eden、s0、s1的大小。同时会动态调整调整三者的大小。采用Copying算法,但在扫描和复制的过程中采用多线程方式。适合于多CPU,对暂停时间要求较短的应用。是server级别默认回收方式。线程数计算方法:CPU核数小于等于8,线程数即核数;核数大于8,线程数=3+(核数*5)/8.或者用-XX:ParallelGCThreads来指定。

c.并行GC(ParNew):需与旧生代CMS GC配合使用。增加了CPU并行处理,算法采用的与串行GC相同的算法。

2.旧生代可用GC

a.串行:基于标记清除和标记整理相结合实现的。对于运行在client模式下的虚拟机是一个很好的选择。

b.并行:1)首先将代空间划分为并行线程个数的区域,然后根据集合对象及并发线程数进行划分(三色着色);2)从左往右进行扫描,寻找第一个值得压缩的存活对象。

c.并发(CMS):free list记录旧生代哪些部分是空闲的。以获取最短回收停顿时间为目标的收集器。重视服务的响应速度,希望系统停顿时间最短,给用户带来较好的体验。

1).初始标记 2)并发标记 3)重新标记  4)并发清除

初始标记仅是标记一下GC Roots能直接关联到的对象,速度很快;并发标记阶段就是进行GC Roots Tracing的过程;而重新标记阶段则是为了修正并发标记期间因用户程序继续运作而导致产生变动的那一部分对象的标记记录;耗时较长时并发标记和并发清除,但可以与用户线程一起工作。

CMS缺点:

1)CMS收集器对CPU资源非常敏感,总吞吐量降低

2)CMS收集器无法处理浮动垃圾,可能出现concurrent mode failure失效而导致一次full gc产生

3)标记清除导致有大量碎片。

d.G1收集器:面向服务端应用。有四个明显特点:并行与并发;分代收集;空间整合;可预测的停顿。从整体上来看是基于标记整理,从局部来看是基于复制算法。

该类收集器特点是将Java堆划分为多个大小相等的独立区域,新生代和老生代不再是物理隔离,而是一部分region的集合。

3.Full GC触发条件

a.旧生代空间不足

b.CMS GC出现promotion failed和concurent mode failure

c.统计得到的Minor GC晋升到旧生代的平均大小大于旧生代的剩余空间。

猜你喜欢

转载自blog.csdn.net/carson0408/article/details/83503815