java9 g1垃圾收集器
在前面的几篇文章中,我已经在InfoQ上介绍并讨论了“垃圾第一垃圾收集器” -G1:一个由所有垃圾收集器来统治它们以及调整垃圾第一垃圾收集器的技巧 。
今天,我想讨论一下JEP 248 ,即将G1设为针对OpenJDK 9的默认GC的建议。从OpenJDK 8开始,吞吐量GC(也称为Parallel GC)以及最近的ParallelOld GC(ParallelOld意味着两者-XX:+ UseParallelGC和-XX:+ UseParallelOldGC已启用)已成为OpenJDK的默认GC。 任何想使用其他垃圾收集算法的人都必须在命令行上显式启用它。 例如,如果要使用G1 GC,则需要在命令行上使用-XX:+ UseG1GC进行选择。
将G1 GC设置为OpenJDK 9的默认GC的提案一直是引起社区关注的主要原因,引起了一些惊人的讨论,并最终导致了对原始提案的更新,以便将条款纳入提供还原为使用并行GC作为默认设置的功能。
您可能熟悉软件优化的权衡:可以针对延迟,吞吐量或占用空间对软件进行优化。 GC优化也是如此,并反映在各种流行的GC中。 您也可以专注于这三个中的两个,但是要针对这三个进行优化非常困难。 OpenJDK HotSpot GC算法旨在优化这三种算法之一-例如,优化串行GC以减少占用空间,优化并行GC以提高吞吐量,并(主要)优化并发标记和扫描GC(通常称为CMS)以最小化GC引起的延迟并提供了改进的响应时间。 那么,为什么我们需要G1?
G1 GC可以长期替代CMS。 当前状态的CMS有一个病理问题,它将导致并发模式故障,最终导致完整的堆压缩集合。 您可以调整CMS以推迟当前的单线程全堆压缩集合,但是最终无法避免。 您可以调整CMS来推迟当前的单线程全堆压缩回退集合,但最终无法避免。 将来,可以改进后备集合,以使用多个GC线程来加快执行速度。 但同样,无法避免完整的压缩集合。
另一个重要的一点是,即使对于经验丰富的GC工程师而言,CMS的维护也被证明是非常困难的。 活跃的HotSpot GC维护人员的目标之一就是保持CMS的稳定。
此外,CMS GC,Parallel GC和G1 GC均通过不同的GC框架实现。 维护三个不同的GC的成本都很高,每个GC都使用自己独特的GC框架。 在我看来,G1 GC的区域化堆框架(集合的单位是一个区域,并且各个此类区域可以组成连续的Java堆中的各个代)是未来的发展方向-IBM拥有其Balanced GC,Azul拥有C4 ,最近有一个称为Shenandoah的OpenJDK提案。 看到类似的基于区域的基于吞吐量的吞吐量GC的实现并不奇怪,它可以提供并行GC的吞吐量和自适应调整大小的好处。 因此,有可能可以减少HotSpot中使用的GC框架的数量,从而降低维护成本,从而可以更快地开发新的GC功能。
G1 GC在OpenJDK 7更新4中得到了完全支持,从那时起,它在OpenJDK社区的大量帮助下变得越来越好,功能越来越强大。 要了解有关G1的更多信息,我强烈推荐前面提到的InfoQ文章,但让我总结一些关键要点:
该提案是针对OpenJDK的9 OpenJDK的9一般可用性是针对2016年九月,这仍然是一个一年。 希望选择使用早期访问版本和候选发布版本的OpenJDK社区成员可以测试G1 GC作为默认GC的可行性,并有助于及时提供反馈,甚至提供代码更改。
同样,唯一受影响的最终用户是那些今天没有设置明确GC的用户。 在命令行上设置显式GC的用户不受此更改的影响。 未明确设置GC的用户将使用G1 GC代替Parallel GC,如果要继续使用Parallel GC,只需设置-XX:+ UseParallelGC(当前的默认设置即可启用并行GC线程用于年轻集合)在其JVM命令行上。 注意:在JDK 5更新6中引入了-XX:+ UseParallelOldGC; 对于所有最近的构建,您会发现,如果在JVM命令行上设置-XX:+ UseParallelGC,还将启用-XX:+ UseParallelOldGC,因此并行GC线程也将用于完整集合。 因此,如果您正在使用> JDK 6构建,则设置这些命令行选项中的任何一个都将提供与以前相同的GC行为。
如本文所述 ,并行GC不进行增量收集,因此最终牺牲了吞吐量的延迟。 对于较大的堆,随着负载增加,GC暂停时间也通常也会增加,这可能会损害与延迟相关的系统级别协议(SLA)。
G1可以帮助您以较小的堆占用空间交付响应时间SLA,因为G1的混合收集暂停应该比Parallel GC中的完整收集要短得多。
在当前状态下,经过调整的G1可以并且将满足CMS GC由于碎片和并发模式故障而无法提供的延迟SLA。 混合集合的最坏情况下的暂停时间预计将比CMS将遇到的最坏情况下的完全压缩暂停更好。 如前所述,可以推迟但不能阻止CMS堆的碎片化。 一些与CMS一起工作的开发人员提出了一些变通方法,以通过将对象分配给类似大小的块来解决碎片问题。 但是这些都是围绕 CMS构建的变通办法; CMS的固有特性是易于碎片化,需要完整的压缩集合。 我也知道像Google这样的公司,他们通过OpenJDK源代码构建并运行自己的私有JDK,并通过更改特定源代码来满足他们的需求。 例如,为了减少碎片,一位Google工程师提到他们在(私有)CMS GC的备注阶段添加了一种增量压缩形式,并使CMS GC更加稳定(请参阅: http:// mail。 openjdk.java.net/pipermail/hotspot-dev/2015-July/019534.html )。
注意:增量压缩会自带成本。 在权衡特定用例的优势后,Google可能会添加增量压缩。
许多OpenJDK社区成员对G1是否准备好迎接黄金时间表示了担忧。 成员们就他们在G1领域的经验发表了意见。 自从G1得到完全支持以来,它一直被誉为CMS的替代品。 但是社区对此感到担忧,因为现在感觉到G1实际上正在取代G1,而不是CMS。 因此,人们普遍认为,尽管可能存在将CMS与G1进行比较的数据(由于企业从CMS迁移至G1),但没有足够的数据将Parallel GC(当前的默认值)与G1(建议的默认值)进行比较。 另外,现场数据似乎表明大多数企业仍在使用默认GC,因此当G1成为默认GC时,肯定会观察到行为的变化。
也有观察发现,G1展示了一些重要的索引损坏问题(尽管很难重现),并且在将G1设置为默认值之前需要研究并纠正这些问题。
还有其他人问我们是否仍需要一个不基于“ 人体工程学 ”的默认GC。 (例如,从Java 5开始,如果您的系统被标识为“服务器级”系统,则默认JVM将更改为服务器VM,而不是客户端VM(参考: http : //docs.oracle.com/javase/7/ docs / technotes / guides / vm / server-class.html ))。
经过反复的反复,最终Oracle的性能架构师Charlie Hunt总结并提出了以下计划(请注意:以下摘录可从此处引用: http : //mail.openjdk.java.net/pipermail/hotspot-dev /2015-June/018804.html ):
此外,Oracle Java SE Performance团队的Staffan Friberg敦促社区帮助收集关键指标的数据点。 为了简明起见,我对斯塔凡的信息进行了解释:
Staffan还帮助确定了当前使用默认GC算法的业务应用程序,这些业务应用程序将受到默认GC更改的影响。 同样,未指定GC的脚本或未在命令行上仅指定Java堆和生成大小的接口都会受到默认GC算法更改的影响。
我要感谢查理·亨特(Charlie Hunt)对本文的审阅。
翻译自: https://www.infoq.com/articles/Make-G1-Default-Garbage-Collector-in-Java-9/?topicPageSponsorship=c1246725-b0a7-43a6-9ef9-68102c8d48e1
java9 g1垃圾收集器