关于java:JVM经典垃圾回收器

51次阅读

共计 3244 个字符,预计需要花费 9 分钟才能阅读完成。

本文已收录至 Github,举荐浏览 👉 Java 随想录
微信公众号:Java 随想录
CSDN:码农 BookSea

转载请在文首注明出处,如发现歹意剽窃 / 搬运,会动用法律武器保护本人的权利。让咱们一起保护一个良好的技术创作环境!

经典垃圾回收器

这一章节不会探讨 CMSG1,因为看完垃圾回收器的章节,我发现书中大部分的篇幅都在探讨 CMSG1。所以会专门开启章节讲述这两个垃圾收集器,这篇还是先探讨除此之外的垃圾回收器。

题目中“经典”二字并非情怀,它其实是探讨范畴的限定语,这里探讨的是在 JDK 7 Update 4 之后(在这个版本中正式提供了商用的 G1 收集器,此前 G1 仍处于试验状态)、JDK 11 正式公布之前,OracleJDK 中的 HotSpot 虚拟机所蕴含的全副可用的垃圾收集器。应用“经典”二字是为了与几款目前仍处于试验状态,但执行成果上有革命性改良的高性能低提早收集器辨别开来,这些经典的收集器只管曾经算不上是最先进的技术,但它们曾在实践中千锤百炼,足够成熟,基本上可认为是当初到将来两、三年内,可能在商用生产环境上放心使用的全副垃圾收集器了。各款经典收集器之间的关系如图:

如果两个收集器之间存在连线,就阐明它们能够搭配应用,图中收集器所处的区域,则示意它是属于新生代收集器抑或是老年代收集器。

Stop The World

Stop The World在垃圾收集器里是十分重要的概念,听 起来这个词有点炫酷,但其实它是 GC” 最大的敌人 ”。之后会屡次呈现,先提前进行阐明。

Stop The World 指的是 GC 事件产生过程中,会产生应用程序的进展。进展产生时整个应用程序线程都会被暂停,没有任何响应, 有点像卡死的感觉,这个进展称为 STW。

为什么要进展,能够在脑海里模仿一个场景:“你妈妈在给你清扫房间的时候,必定也会让你老老实实地在椅子上或者房间外待着,如果她一边清扫,你一边乱扔纸屑,这房间还能清扫完?”

这里另外介绍一个概念,GC 优化个别有两个指标:低提早和高吞吐。很惋惜的是这两个指标往往无奈同时达成,低提早有时是就义高吞吐换得的,反之亦然。这点在之后的 CMS 垃圾回收器会有体现。

Serial 收集器

Serial 收集器是最根底、历史最悠久的收集器,已经(在 JDK 1.3.1 之前)是 HotSpot 虚拟机新生代收集器的惟一抉择。

这个收集器是一个单线程工作的收集器,但它的“单线程”的意义并不仅仅是阐明它只会应用一个处理器或一条收集线程去实现垃圾收集工作,更重要的是强调在它进行垃圾收集时,必须暂停其余所有工作线程,直到它收集完结。

看起来貌似 Serial 并不非常敌对,要暂停其余工作线程,但事实上,迄今为止,它仍然是 HotSpot 虚拟机运行在客户端模式下的默认新生代收集器,有着优于其余收集器的中央,那就是简略而高效,对于内存资源受限的环境,它是所有收集器里额定内存耗费最小的(这点跟 G1 相比就非常显著,G1 的内存耗费是十分大的,之后在 G1 篇会给出起因)。

ParNew 收集器

ParNew 收集器本质上是 Serial 收集器的多线程并行版本,除了同时应用多条线程进行垃圾收集之外,其余的行为包含 Serial 收集器可用的所有控制参数(例如:-XX:SurvivorRatio、-XX:PretenureSizeThreshold、-XX:HandlePromotionFailure 等)、收集算法、Stop The World、对象调配规定、回收策略等都与 Serial 收集器完全一致,在实现上这两种收集器也共用了相当多的代码。

ParNew 收集器除了反对多线程并行收集之外,其余与 Serial 收集器相比并没有太多翻新之处,然而他有一个很牛 B 的特点:除了 Serial 收集器外,目前只有它能与 CMS 收集器配合工作。ParNew 收集器是激活 CMS 后(应用 -XX:+UseConcMarkSweepGC 选项)的默认新生代收集器,也能够应用 -XX:+/-UseParNewGC 选项来强制指定或者禁用它。然而自 JDK 9 开始勾销了 ParNew 加 Serial Old 以及 Serial 加 CMS 这两组收集器组合的反对,并间接勾销了 -XX:+UseParNewGC 参数,这意味着 ParNew 和 CMS 从此只能相互搭配应用 ,再也没有其余收集器可能和它们配合了。 为什么要这么干——因为 G1 来了。

ParNew 默认开启的收集线程数与处理器外围数量雷同 ,能够应用-XX:ParallelGCThreads 参数来限度垃圾收集的线程数。

Parallel Scavenge 收集器

Parallel Scavenge 收集器基于标记 - 复制算法实现,是 JDK8 默认的新生代收集器。与咱们后面说过垃圾收集器最大的不同就是,CMS 等收集器的关注点是尽可能地缩短垃圾收集时用户线程的进展工夫,而 Parallel Scavenge 收集器的指标则是达到一个 可管制 的吞吐量(Throughput)。所谓吞吐量就是处理器用于运行用户代码的工夫与处理器总耗费工夫的比值,即:

如果虚拟机实现某个工作,用户代码加上垃圾收集总共消耗了 100 分钟,其中垃圾收集花掉 1 分钟,那吞吐量就是 99%。

留神字体加粗的中央:可管制。

如何体现可管制?Parallel Scavenge 收集器提供了两个参数用于准确管制吞吐量,别离是管制最大垃圾收集进展工夫的 -XX:MaxGCPauseMillis 参数以及间接设置吞吐量大小的 -XX:GCTimeRatio 参数。

-XX:MaxGCPauseMillis参数容许的值是一个大于 0 的毫秒数,收集器将尽力保障内存回收破费的工夫不超过用户设定值。不过大家不要胡思乱想地认为如果把这个参数的值设置得更小一点就能使得零碎的垃圾收集速度变得更快,垃圾收集进展工夫缩短是以就义吞吐量和新生代空间为代价换取的:零碎把新生代调得小一些,收集 300MB 新生代必定比收集 500MB 快,但这也间接导致垃圾收集产生得更频繁,原来 10 秒收集一次、每次进展 100 毫秒,当初变成 5 秒收集一次、每次进展 70 毫秒。进展工夫确实在降落,但吞吐量也降下来了。

-XX:GCTimeRatio参数的值则该当是一个大于 0 小于 100 的整数,也就是垃圾收集工夫占总工夫的比率,相当于吞吐量的倒数。譬如把此参数设置为 19,那容许的最大垃圾收集工夫就占总工夫的 5%(即 1 /(1+19)),默认值为 99,即容许最大 1%(即 1 /(1+99))的垃圾收集工夫。

除上述两个参数之外,Parallel Scavenge 收集器还有一个参数 -XX:+UseAdaptiveSizePolicy 值得咱们关注。

我看到这里的时候感觉这个参数真滴牛皮。

当这个参数被激活之后,就不须要人工指定新生代的大小(-Xmn)、Eden 与 Survivor 区的比例(-XX:SurvivorRatio)、降职老年代对象大小(-XXPretenureSizeThreshold)等细节参数了,虚构机会依据以后零碎的运行状况收集性能监控信息,动静调整这些参数以提供最合适的进展工夫或者最大的吞吐量。

如果对于 Parallel Scavenge 收集器不太理解,开启这个参数,把内存治理的调优工作交给虚拟机去实现是一个不错的抉择,几乎就是小白福音

Serial Old

Serial Old 是 Serial 收集器的老年代版本,它同样是一个单线程收集器,应用 标记 - 整顿 算法。这个收集器的次要意义也是供客户端模式下的 HotSpot 虚拟机应用。如果在服务端模式下,它也可能有两种用处:一种是在 JDK 5 以及之前的版本中与 Parallel Scavenge 收集器搭配应用,另外一种就是作为 CMS 收集器产生失败时的后备预案,在并发收集产生 Concurrent Mode Failure 时应用。

Parallel Old 收集器

Parallel Old 是 Parallel Scavenge 收集器的老年代版本,反对多线程并发收集,基于标记 - 整顿算法实现。

Parallel Scavenge+Parallel Old 被称为吞吐量优先组合

正文完
 0