JVM垃圾收集器(GC)有哪些?

点击上方「蓝字」关注我们

上文:JVM执行引擎(Execution Engine)


什么是垃圾?

    对于jvm来说垃圾是指运行程序中没有任何指针指向的对象,这个对象就需要被回收。

    个人理解:对于个人所需来说,比如你家里拆快递盒子,用过后,你一直不用,要及时清除,要不然很容易把房间堆满,那这样的话后面的放不进去物品了。

为什么需要GC?

    对于高级语言来讲,因为不断的创建对象,如果不清理,迟早内存会满。所以需要清理不要的垃圾。这个有点类型你家里有一间储存物品的杂货间,如果一直往里面塞东西而又不梳理,迟早有一天会被塞满的。

什么是垃圾收集器GC?

    垃圾收集器全称:Garbage Collection,下文简称GC,其实就是各种垃圾算法的一种实现。目前还没有符合所有场景的收集器出现。

并行和并发的区别?

    并行(Parallel):指多条垃圾收集线程并行工作,但此时用户线程仍然处于等待状态。

    并发(Concurrent):指用户线程与垃圾收集线程同时执行(但不一定是并行的,可能会交替执行),用户程序在继续运行。而垃圾收集程序运行在另一个CPU上。

有哪些垃圾收集器?

    串行垃圾回收器(Serial)

    JVM第一个垃圾收集器,JDK 1.3.1之前都是有这个收集器。可以作用新生代和老年代。

    算法:新生代-使用复制算法,老年代-使用标记-整理算法。

    特点:串行单线程、不支持并发、会导致"stop the world"。

//配置如下使用
 -XX:+UseSerialGC

并发垃圾回收器(parNew)

    为了解决 serial拉圾收集器引起的停机问题,在serial基础上开发了多线程版本,但是parNew是针对client的版本。

特点:多线程、唯一能够与cms搭配使用的收集器;

算法:年轻代采用复制算法、年老代采用标记-整理

//强制指定使用ParNew;
 -XX:+UseParNewGC
//指定垃圾收集的线程数量,ParNew默认开启的收集线程与CPU的数量相同;
-XX:ParallerGCThreads

并行垃圾收集器(Parallel Scavenge)

Parallel Scavenge是后个多线程新生代收集器,使用的算法是复制算法。实现方式是当垃圾达到一个可控制的吞吐量(Throughput)则启动垃圾回收。

特点:作用于新生代、老年代由Serial搭配使用,可以有效的减少停顿时间提升用户体验。

算法:新生代复制算法,老年代标记整理

//注意:启动后不需要手工指定新生代的大小(-Xmn)、Eden和Survivor区的比例(-XX:SurvivorRatio)、晋升老年代对象年龄(-XX:PretenureSizeThreshold)等细节参数了
-XX:+UseAdaptiveSizePolicy
//使用Parallel收集器+老年代串行 
-XX:+UseParallelGC 
//启用并行压缩 
-XX:+UseParallelOldGC。

并发垃圾回收器 CMS(Concurrent Mark Sweep)

cms主要是解决停顿时间的问题而开发的一种,低停顿、并发收集器,基于标记清除,可以作用于新生代和老年代。

CMS收集器的运行过程分为下列4步:

初始标记:标记GC Roots能直接到的对象。速度很快但是仍存在Stop The World问题。

并发标记:进行GC Roots Tracing 的过程,找出存活对象且用户线程可并发执行。

重新标记:为了修正并发标记期间因用户程序继续运行而导致标记产生变动的那一部分对象的标记记录。仍然存在Stop The World问题。

并发清除:对标记的对象进行清除回收。

特点:作用于新生代、老年代、代停顿、并发收集;

算法:标记-清除;

缺点:无法处理浮动垃圾、对CPU资源非常敏感、会造成空间碎片化;

//新生代使用并行收集器,老年代使用CMS+串行收集器
-XX:+UseConcMarkSweepGC
//设定CMS的线程数量 
-XX:ParallelCMSThreads

G1垃圾回收器(G1)

特点:作用于新生代、老年代、空间连续减少垃圾碎片、缩小回收范围减少全局停顿、并发收集;

算法:分区算法;

缺点:无法处理浮动垃圾、对CPU资源非常敏感、会造成空间碎片化;

G1收集器的阶段分以下几个步骤:

1、初始标记(它标记了从GC Root开始直接可达的对象);

2、并发标记(从GC Roots开始对堆中对象进行可达性分析,找出存活对象);

3、最终标记(标记那些在并发标记阶段发生变化的对象,将被回收);

4、筛选回收(首先对各个Regin的回收价值和成本进行排序,根据用户所期待的GC停顿时间指定回收计划,回收一部分Region)。

//启用G1垃圾回收器 -XX:+UseG1GC

查看jdk所用内存垃圾回收器

通过命令:

java   -XX:+PrintCommandLineFlags -version

堆大小的计算?

初始堆大小

memory / DefaultInitialRAMFraction

memory / 64

最大堆大小

MIN(memory / DefaultMaxRAMFraction, 1GB)

MIN(memory / 4, 1GB)

在JDK8默认的配置下使用 新生代,老年代的垃圾回收策略,新生代区域使用标记-复制算法,老年代区域使用标记-整理算法。

收集器

类型

区域

算法

特性

场景

Seial

串行

新生代

复制算法

响应速度优化

单CPU环境下的Client模式

Serial Old

串行

老年代

标记-整理

响应速度优化

单CPU环境下的Client模式、CMS的后备预案

ParNew

并行

新生代

复制算法

响应速度优先

多CPU环境时在Server模式下与CMS配合

Parallel Scavenge

并行

新生代

复制算法

吞吐量优先

后台运算不需要太多交互任务

Parallel Scavenge old

并行

老年代

标记整理

吞吐量优先

后台运算不需要太多交互任务

CMS

并发

老年代

标记清除

响应速度优先

主要用于互联网站或B/S系统服务端上的Java应用

G1

并发

新生代/老年代

标记-整理+复制算法

响应速度优先

面向服务端应用,将来替换CMS

新生代收集器:Serial、ParNew、Parallel Scavenge

老年代收集器:CMS、Serial Old、Parallel Old

整堆收集器:G1

GC的参数整理

-XX:+UseSerialGC:在新生代和老年代使用串行收集器
-XX:SurvivorRatio:设置eden区大小和survivior区大小的比例
-XX:NewRatio:新生代和老年代的比
-XX:+UseParNewGC:在新生代使用并行收集器
-XX:+UseParallelGC :在新生代使用并行回收收集器
-XX:+UseParallelOldGC:老年代使用并行回收收集器
-XX:ParallelGCThreads:设置用于垃圾回收的线程数
-XX:+UseConcMarkSweepGC:新生代使用并行收集器,老年代使用CMS+串行收集器
-XX:ParallelCMSThreads:设定CMS的线程数量
-XX:CMSInitiatingOccupancyFraction:设置CMS收集器在老年代空间被使用多少后触发
-XX:+UseCMSCompactAtFullCollection:设置CMS收集器在完成垃圾收集后是否要进行一次内存碎片的整理
-XX:CMSFullGCsBeforeCompaction:设定进行多少次CMS垃圾回收后,进行一次内存压缩
-XX:+CMSClassUnloadingEnabled:允许对类元数据进行回收
-XX:CMSInitiatingPermOccupancyFraction:当永久区占用率达到这一百分比时,启动CMS回收
-XX:UseCMSInitiatingOccupancyOnly:表示只在到达阀值的时候,才进行CMS回收

最后

    jvm的垃圾收集器主要作用于新生代和老年代,不同的版本和不同的收集群可以针对不同的场景需要,并不意味的最新就是最好的,有时候在架构和业务层面考虑,可以根据需要进行配置,当然本文仅介绍垃圾收集器,具体里面的算法,由下文再继续深入。

参考文章:

    https://blog.51cto.com/u_6877873/1743686

    https://www.oracle.com/java/technologies/javase/gc-tuning-6.html

    https://www.cnblogs.com/chenpt/p/9803298.html

    https://zhuanlan.zhihu.com/p/58896619

往期推荐

JVM执行引擎(Execution Engine)

spring整合各种中间件(RocketMQ、kafka、RabbitMQ、ActiveMQ、ZeroMQ、TubeMQ)NSQ

NSQ基于windows和docker的部署

没有打印日志,如何排查线上问题?——arthas(阿尔萨斯)

云原生是什么?(Cloud Native)

JVM-直接内存(Direct Memory)

spring整合各种中间件(RocketMQ、kafka、RabbitMQ、TubeMQ、NSQ)-腾讯开源【TubeMQ】

怎么样学习java最快?

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值