JVM垃圾回收器

JVM垃圾回收器

一、概述

如果说前面介绍的收集算法(JVM之垃圾回收-垃圾收集算法)是内存回收的抽象策略,那么垃圾收集器就是内存回收的具体实现。https://blog.csdn.net/qq_26525215/article/details/84294481
JVM规范对于垃圾收集器的应该如何实现没有任何规定,因此不同的厂商、不同版本的虚拟机所提供的垃圾收集器差别较大,这里只看HotSpot虚拟机。
就像没有最好的算法一样,垃圾收集器也没有最好,只有最合适。我们能做的就是根据具体的应用场景选择最合适的垃圾收集器。

二、Serial(串行)收集器

Serial(串行)收集器收集器是最基本、历史最悠久的垃圾收集器了(新生代采用复制算法,老生代采用标志整理算法)。是一个单线程收集器。
GC时只会使用一条垃圾收集线程去完成垃圾收集工作,在进行垃圾收集工作的时候必须暂停其他所有的用户线程,直到该垃圾收集线程收集结束。
示例图 – >
在这里插入图片描述
上图中:
1)新生代采用复制算法,Stop-The-World
2)老年代采用标记-整理算法,Stop-The-World
缺点:

  1. 执行GC时,不管是新生代还是老年代,都会中断所有的用户线程
  2. 如果服务器为多cpu时,大大浪费了服务器的CPU性能
    优点/使用场景:
    对于限定单个CPU的环境来说,没有线程交互的开销,专心做GC,自然可以获得最高的单线程效率。所以Serial收集器适用运行在client模式下的应用
    设置参数 :
    添加该参数来显式的使用串行垃圾收集器:
    “-XX:+UseSerialGC”

三、ParNew收集器(Serial收集器的多线程版本)

ParNew收集器其实就是Serial收集器的多线程版本,除了使用多线程进行垃圾收集外,其余行为(控制参数、收集算法、回收策略等等)和Serial收集器完全一样。
它是许多运行在Server模式下的虚拟机的首要选择,除了Serial收集器外,目前只有它能与CMS收集器配合工作。
在这里插入图片描述
上图中:
1)新生代采用复制算法,多线程执行GC,Stop-The-World
2)老年代采用标记-整理算法,单线程执行GC,Stop-The-World

应用场景:
在Server模式下,ParNew收集器是一个非常重要的收集器,因为除Serial外,目前只有它能与CMS收集器配合工作;
但在单个CPU环境中,不会比Serail收集器有更好的效果,因为存在线程交互开销。
设置参数:
指定使用CMS后,会默认使用ParNew作为新生代收集:
“-XX:+UseConcMarkSweepGC”
强制指定使用ParNew:
“-XX:+UseParNewGC”
指定垃圾收集的线程数量,ParNew默认开启的收集线程与CPU的数量相:
“-XX:ParallelGCThreads”

四、Parallel Scavenge收集器

Parallel Scavenge收集器是一个新生代收集器,它也是使用复制算法的收集器,又是并行的多线程收集器。
Parallel Scavenge收集器关注点是吞吐量(如何高效率的利用CPU)。
所谓吞吐量就是CPU中用于运行用户代码的时间与CPU总消耗时间的比值。
吞吐量:
吞吐量=运行用户代码的时间/(运行用户代码时间+垃圾收集时间)。

比如,虚拟机总共运行了100分钟,其中垃圾收集花掉1分钟,那吞吐量就是99%。)
在这里插入图片描述
特点:
1.新生代收集器;
2.采用复制算法;
3.多线程收集;
4.CMS等收集器的关注点是尽可能地缩短垃圾收集时用户线程的停顿时间;而Parallel Scavenge收集器的目标则是达一个可控制的吞吐量(垃圾回收停顿时间参数可控制);
应用场景:
高吞吐量为目标,即减少垃圾收集时间,让用户代码获得更长的运行时间;
当应用程序运行在具有多个CPU上,对暂停时间没有特别高的要求时,即程序主要在后台进行计算,而不需要与用户进行太多交互;
例如,那些执行批量处理、订单处理(对账等)、工资支付、科学计算的应用程序;
设置参数:
Parallel Scavenge收集器提供两个参数用于精确控制吞吐量:
A)控制最大垃圾收集停顿时间:
“-XX:MaxGCPauseMillis” 控制最大垃圾收集停顿时间,大于0的毫秒数;
MaxGCPauseMillis设置得稍小,停顿时间可能会缩短,但也可能会使得吞吐量下降;因为可能导致垃圾收集发生得更频繁;
B)设置垃圾收集时间占总时间的比率
“-XX:GCTimeRatio”
设置垃圾收集时间占总时间的比率,0 < n < 100的整数;
GCTimeRatio相当于设置吞吐量大小;
垃圾收集执行时间占应用程序执行时间的比例的计算方法是: 1 / (1 + n) 。
例如,选项-XX:GCTimeRatio=19,设置了垃圾收集时间占总时间的5% = 1/(1+19);默认值是1% = 1/(1+99),即n=99;

垃圾收集所花费的时间是年轻一代和老年代收集的总时间;
如果没有满足吞吐量目标,则增加代的内存大小以尽量增加用户程序运行的时间;

GC自适应的调节策略(GC Ergonomics)
另外还有一个参数:
“-XX:+UseAdptiveSizePolicy”

五、Serial Old收集器

Serial收集器的老年代版本,它同样是一个单线程收集器。采用标记–整理算法
它主要有两大用途:一种用途是在JDK1.5以及以前的版本中与Parallel Scavenge收集器搭配使用,另一种用途是作为CMS收集器的后备方案
在这里插入图片描述

六、Parallel Old收集器

Parallel Scavenge收集器的老年代版本。
使用多线程和“标记-整理”算法。在注重吞吐量以及CPU资源的场合,都可以优先考虑 Parallel Scavenge收集器和Parallel Old收集器。
在这里插入图片描述

七、CMS回收器

从名字中的Mark Sweep这两个词可以看出,CMS收集器是一种 “标记-清除”算法实现的,它的运作过程相比于前面几种垃圾收集器来说更加复杂一些。整个过程可分为四个步骤:
四个步骤:
GC算法中的三色标记算法怎么理解?
trace GC将对象分为三类:白色(垃圾收集器未探测到的对象)、灰色(活着的对象,但是依然没有被垃圾收集器扫描过)、黑色(活着的对象,并且已经被垃圾收集器扫描过)。垃圾收集器的工作过程,就是通过灰色对象的指针扫描它指向的白色对象,如果找到一个白色对象,就将它设置为灰色,如果某个灰色对象的可达对象已经全部找完,就将它设置为黑色对象。当在当前集合中找不到灰色的对象时,就说明该集合的回收动作完成,然后所有白色的对象的都会被回收
1.初始标记:
暂停所有的其他线程,初始标记仅仅标记GC Roots能直接关联到的对象(也就是GC Roots和它的子对象),速度很快,之后的可达性分析交给并发标记的GC线程完成
在这里插入图片描述
2.并发标记:
并发标记就是进行GC Roots Tracing的过程
同时开启GC和用户线程,用一个闭包结构去记录可达对象。但在这个阶段结束,这个闭包结构并不能保证包含当前所有的可达对象。因为用户线程可能会不断的更新引用域,所以GC线程无法保证可达性分析的实时性。所以这个算法里会跟踪记录这些发生引用更新的地方
3.重新标记:
重新标记阶段就是为了修正并发标记期间因为用户程序继续运行而导致标记产生变动的那一部分对象的标记记录(采用多线程并行执行来提升效率);需要"Stop The World",且停顿时间比初始标记稍长,但远比并发标记短
4.并发清除:
开启用户线程,同时GC线程开始对为标记的区域做清扫,回收所有的垃圾对象
由于整个过程耗时最长的并发标记和并发清除过程收集器线程都可以与用户线程一起工作。
所以总体来说,CMS的内存回收是与用户线程一起“并发”执行的。
在这里插入图片描述
缺点:
1.CMS的默认收集线程数量是=(CPU数量+3)/4; 当CPU数量越多,回收的线程占用CPU就少。如果当前cpu为2时,并发标记需要占用一个线程,CPU 的50 % 。
2.CMS作用于老年代,采用的是 “标记 – 清除” 算法,会产生大量的不连续内存空间,长时间运行后会产生大量的空间碎片问题,可能导致新生代对象晋升到老生代失败。
解决办法:
需要结合使用。
“-XX:+UseCMSCompactAtFullCollection” 执行完成后做一次整理操作
“-XX:+CMSFullGCsBeforeCompaction” 执行多少次FullGC 做一次整理操作
3.并发清除的阶段,无法回收用户线程新产生的垃圾(浮动垃圾),这时候会有从新生代(Eden,TO,From)晋升到老年代的对象,所有CMS必须在GC时预留一部分的内存空间,CMS默认阈值为68%的时候,执行GC
解决办法:使用"-XX:CMSInitiatingOccupancyFraction",设置CMS预留老年代内存空间; (详解见名词解释)

八、G1回收器

上一代的垃圾收集器(串行serial, 并行parallel, 以及CMS)都把堆内存划分为固定大小的三个部分: 年轻代(young generation), 年老代(old generation), 以及持久代(permanent generation)。
G1算法将堆划分为若干个区域( Region),但它仍然属于分代收集器。
不过,这些区域的部分包含新生代,新生代的垃圾收集依然采用暂停所有应用线程的方式,将存活对象拷贝到老年代或者 Survivor空间。
老年代也分成很多区域,G1收集器通过将对象从一个区域复制到号外一个区域,成了洁理工作,这就味者在正常的处理过程中,(1完成了雄的压縮(至少是部分堆的压缩),这样也航不会有CMS内有片问的存在了
在这里插入图片描述
在这里插入图片描述
G1的使命是在未来替换CMS,并且在JDK1.9已经成为默认的收集器。
G1采用了两种方式
Young GC
Mixed

从整体看,是基于标记-整理算法;
从局部(两个Region间)看,是基于复制算法;

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值