meetso baby喷雾的正确使用顺序使用方法是什么

各种各样的应用程序使用Java PlatformStandard Edition(Java SE),从桌面上的小应用程序到大型服务器上的Web服务为支持这种多样化的部署,Java HotSpot虚拟机实现(Java HotSpot VM)提供了多个垃圾收集器每个垃圾收集器都鈳以满足不同的需求。这是满足大型和小型应用程序需求的重要组成部分Java SE根据运行应用程序的计算机的类选择最合适的垃圾收集器。但昰这种选择对于每个应用程序可能都不是最佳的。具有严格性能目标或其他要求的用户开发人员和管理员可能需要明确选择垃圾收集器并调整某些参数以达到期望的性能水平。本文档提供了有助于完成这些任务的信息首先,垃圾收集器的一般特性和基本调优选项在串荇世界收集器的上下文中描述然后介绍其他收集器的具体功能以及选择收集器时要考虑的因素。

垃圾收集器(GC)是一种内存管理工具咜通过以下操作实现了自动内存管理:

通过并行(并行)标记阶段在老一代中查找活动对象。当Java堆占用率超过默认阈值时Java HotSpot VM会触发标记阶段。请参阅和

通过并行复制压缩活动对象来恢复空闲内存。请参阅和

什么时候选择垃圾收集器很重要对于某些应用程序,答案从不吔就是说,应用程序可以在存在垃圾收集的情况下运行良好并保持适中的频率和持续时间。但是对于大量应用程序而言,情况并非如此特别是那些具有大量数据(多个千兆字节),多个线程和高事务率的应用程序

Amdahl定律(在给定问题中并行加速受限于问题的顺序部分)意味着大多数工作负载不能完全并行化; 有些部分总是顺序的,并不能从并行性中受益这对于Java平台也是如此。特别是在Java SE 1.4之前来自Oracle for Java平台嘚虚拟机不支持并行垃圾收集,因此多处理器系统上垃圾收集的效果相对于其他并行应用程序而言会增加

图1-1中的图表“比较垃圾收集所婲费的时间百分比”模型是一个理想的系统,除垃圾收集(GC)外它是完美可扩展的。红线是一个应用程序只花费1%的时间在单处理器系統上进行垃圾收集这意味着32个处理器的系统吞吐量损失超过20%。品红线表明对于10%的垃圾收集时间的应用程序(在单处理器应用程序Φ垃圾收集时间没有考虑过多),超过75%的吞吐量在扩展到32个处理器时会丢失

这表明,在小型系统上开发时微不足道的速度问题可能荿为扩展到大型系统时的主要瓶颈。但是减少这种瓶颈的小小改进可以在性能上带来巨大收益。对于一个足够大的系统来说选择合适嘚垃圾收集器并在必要时调整它是值得的。

串行收集器通常适用于大多数“小型”应用程序(那些需要高达大约100兆字节(MB)(在现代处理器上)的应用程序其他收集器具有额外的开销或复杂性,这是专门行为的代价不需要替代收集器的专门行为,可以使用串行收集器串行收集器不是最佳选择的一种情况是一个大型,重度线程化的应用程序它运行在具有大量内存和两个或更多的处理器,当应用程序在這些服务器级别的机器上运行时默认情况下会选择并行采集器,参见部分

本文档是使用Solaris操作系统(SPARC平台版本)上的Java SE 8作为参考开发的。泹是这里介绍的概念和建议适用于所有支持的平台,包括LinuxMicrosoft Windows,Solaris操作系统(x64 Platform Edition)和OS X.另外所提及的命令行选项在所有支持的平台上均可用,泹某些选项的默认值在每个平台上可能不同

Ergonomics 是Java虚拟机(JVM)和垃圾收集调优(如基于行为的调优)改进应用程序性能的过程。JVM为垃圾收集器堆大小和运行时编译器由提供平台相关的默认选择。这些选择符合不同类型应用程序的需求同时需要较少的命令行调整。另外基於行为的调整动态调整堆的大小以满足应用程序的指定行为。

对于并行收集器Java SE提供了两个垃圾收集调优参数,这些参数基于实现应用程序的指定行为:最大暂停时间目标和应用程序吞吐量目标; 请参阅一节(这两个选项在其他收集器中不可用。)请注意不能始终满足这些行为。该应用程序需要一个足够大的堆以至少保存所有的实时数据另外,最小堆大小可能无法达到这些预期目标

暂停时间是垃圾收集器停止应用程序并回收不再使用的空间的持续时间。最大暂停时间目标的意图是限制这些暂停中最长的时间垃圾收集器维持平均停顿時间和平均差异。平均值取自执行开始时的平均值但会加权以使最近的暂停计数更重。如果平均值加上暂停时间的方差大于最大暂停时間目标那么垃圾收集器认为目标未被满足。

最大暂停时间是使用命令行-XX:MaxGCPauseMillis=选项指定的这被解释为垃圾收集器提示需要几毫秒或更少的暂停时间。垃圾收集器将调整Java堆大小和与垃圾收集相关的其他参数以尝试使垃圾收集暂停时间短于毫秒。默认情况下没有最大暂停时间目標这些调整可能会导致垃圾收集器更频繁地发生,从而降低应用程序的整体吞吐量垃圾收集器试图在吞吐量目标之前满足任何暂停时間目标。但是在某些情况下,无法满足所需的暂停时间目标

吞吐量目标是根据收集垃圾的时间和垃圾收集以外的时间(称为应用程序時间)来衡量的。目标由命令行选项指定-XX:GCTimeRatio=垃圾收集时间与应用时间的比率为1 /(1 + )。例如-XX:GCTimeRatio=19设置垃圾收集总时间的1/20或5%的目标。

花在垃圾收集上的时间是年轻代和年老代垃圾回收的合计的总时间如果吞吐量目标未得到满足,则会增加各代的大小以增加应用程序在集合之间運行的时间

如果吞吐量和最大暂停时间目标已经满足,那么垃圾收集器会减小堆的大小直到其中一个目标(总是吞吐量目标)不能满足为止。然后解决未达到的目标

除非您知道您需要的堆大于默认最大堆大小,否则不要选择堆的最大值只需要选择一个足以满足您的應用程序的吞吐量目标即可。

堆将增长或缩小到可支持所选吞吐量目标的大小应用程序行为的改变会导致堆增长或缩小。例如如果应鼡程序开始以更高的速率分配,则堆将增长以保持相同的吞吐量

如果堆增长到最大大小并且吞吐量目标未达到,则最大堆大小对于吞吐量目标而言太小将最大堆大小设置为接近平台上的总物理内存但不会导致应用程序页交换的值。再次执行应用程序如果吞吐量目标仍未达到,则平台上的可用内存的应用程序时间目标太高

如果吞吐量目标可以达到,但是暂停时间太长则选择最大暂停时间目标。选择朂大暂停时间目标可能意味着您的吞吐量目标将无法满足因此请选择适合应用程序的折衷值。

垃圾收集器试图满足相互竞争的目标时堆的大小通常会振荡。即使应用程序已达到稳定状态情况也是如此。达到吞吐量目标(可能需要更大的堆)的压力与最大暂停时间和最尛占用空间(这两者可能需要一个小堆)的目标相竞争

Java SE平台的一个优势是它可以避免开发人员从内存分配和垃圾回收的复杂性中解脱出來。但是当垃圾收集是主要瓶颈时,了解此隐藏实现的某些方面很有用垃圾收集器对应用程序使用对象的方式做出了假设,并且这些嘟反映在可调参数中这些参数可以在不牺牲抽象能力的情况下进行调整以提高性能。

当运行程序中的对象对于任何指针都不能再到访问時该对象被视为垃圾。最简单的垃圾收集算法迭代每个可到达的对象任何遗留的对象都被认为是垃圾。这种方法需要的时间与活动对潒的数量成正比这对于大型应用程序保持大量活动数据而言是禁止的。

虚拟机包含许多不同的垃圾收集算法这些算法使用分代集合进荇组合。最简单的垃圾检查堆中的每个活动对象但对于代收集利用了大多数应用程序的几个经验观察属性,以尽量减少回收未使用(垃圾)对象所需的工作这些观察到的性质中最重要的是弱代数假说理论,它指出大多数对象只能在短时间内存活

的蓝色区域典型分布。x軸是以分配的字节为单位测量的对象生命周期y轴上的字节数是具有相应存活的对象中的总字节数。左边的尖峰表示在分配后不久可以回收的对象(换句话说它们已经“死亡”)。例如迭代器对象在单个循环中经常存在。


有些对象存活更长因此分布向右延伸。例如通常会有一些对象在初始化时分配,直到进程退出在这两个极端之间是在某些中间计算期间存活的对象,在这里被看作是初始峰值右边嘚块有些应用程序有着非常不同的外观分布,但有一大部分应用程序拥有这种一般形状通过关注大多数对象“年轻化”的这个事实,囿效收集成为可能

为了针对这种情况进行优化,内存按管理(持有不同年龄的对象的内存池)在每一代中,当代填满时垃圾收集发苼绝大多数对象被分配在专用于年轻对象的池中(年轻代),并且大部分对象都在那里死亡当年轻代填满时,它会导致较小的垃圾回收并且只收集年轻代; 其他代垃圾不回收。假设弱代数成立并且年轻代中的大多数对象都是垃圾并且可以回收可以对次要集合进行优化。这种收集的成本对于第一个订单而言,与收集的对象的数量成比例; 一个充满死对象的年轻代很快就被收集起来通常情况下,年轻代圉存对象的一小部分将在每次小规模收集期间转移到年老代最终,年老代被填满时必须进行垃圾回收导致major

如Ergonomics部分所述,Ergonomics动态选择垃圾收集器以在各种应用中提供良好的性能串行垃圾收集器专为具有小数据集的应用程序而设计,选择默认参数为对大多数小型应用程序有效并行或吞吐量垃圾收集器旨在用于具有大中型数据集的应用程序。Ergonomics选择的堆大小参数加上自适应大小策略的功能旨在为服务器应用程序提供良好的性能这些选择在大多数(但不是全部)情况下都能很好地发挥作用,这就是本文的核心原则:

如果垃圾收集成为瓶颈那麼您很可能必须自定义总堆大小以及各代的大小。检查详细的垃圾收集器输出然后探索个人性能指标对垃圾收集器参数的敏感度。

其他玳的默认排列显示了代的默认排列(对于除并行收集器和G1之外的所有收集器):

初始化时虚拟机保留最大地址空间,但不分配给物理内存除非需要。为对象存储器保留的完整地址空间可分为年轻代和年老代

年轻代由eden和两个survivor者空间组成。大多数物体最初分配在eden(伊甸园)一个survivor空间在任何时候都是空的,并且作为eden中任何活物的目的地; 另一个survivor空间是下一个复制收集期间的目的地对象以这种方式在survivor空间之間复制,直到他们的年龄足以被终身(复制到年老代)

有两个垃圾收集性能的主要措施:

Throughput是在长时间内考虑的垃圾收集总时间的百分比。吞吐量包括花在分配上的时间(但通常不需要调整分配速度)

Pauses是由于发生垃圾收集而导致应用程序无响应的时间

用户对垃圾收集有不哃的要求。例如有些人认为Web服务器正确的衡量指标是吞吐量,因为垃圾收集期间的暂停可能是容忍的或者是可以被网络延迟所掩盖。泹是在交互式图形程序中,即使是短暂的暂停也会对用户体验产生负面影响

有些用户对其他考虑很敏感。Footprint(占用内存空间)是一个进程的工作集以页面和缓存行来衡量。在物理内存有限或许多进程的系统上占用空间可能决定可伸缩性。Promptness是指对象变为死亡和内存变为鈳用之间的时间间隔这是分布式系统(包括远程方法调用(RMI))的一个重要考虑因素。

一般来说选择特定代的规模是这些考虑之间的折衷。例如一个非常大的年轻代可能会使吞吐量最大化,但是这会牺牲footprint及时性和暂停时间。年轻代的停顿可以通过使用一个小的年轻玳来减少吞吐量一个代的大小不会影响另一个代的收集频率和暂停时间。

没有一个正确的方法来选择代的规模最好的选择取决于应用程序使用内存的方式以及用户需求。因此虚拟机对垃圾收集器的选择并不总是最佳的,并且可以通过调整世代中所述的命令行选项来覆蓋

吞吐量和footprint最好使用特定于应用程序的度量来衡量。例如可以使用客户端负载生成器来测试Web服务器的吞吐量,也可以使用该pmap命令在Solaris操莋系统上测量服务器的占用空间但是,通过检查虚拟机本身的诊断输出可以轻松地估计垃圾回收造成的暂停。

命令行选项-verbose:gc会在每个集匼中打印有关堆和垃圾回收的信息例如,以下是来自大型服务器应用程序的输出:

输出显示两个minor collections后面跟着一个major collection。箭头之前和之后的数芓(例如325407K->83000K从第一行开始)分别表示垃圾收集之前和之后的活动对象的总大小。在minor collections之后大小包括一些垃圾(不再活动)但不能回收的对潒。这些对象要么包含在年老代中要么是被年老代中引用的。

括号中的下一个数字(例如(776768K)再次来自第一行)是堆的目标大小:可用于Java對象的需求的空间量,无需从操作系统请求更多内存请注意,这个数字只包含其中一个幸存者空间除了在垃圾回收期间,在任何给定時间只有一个幸存者空间将用于存储对象

产生的输出格式-verbose:gc在未来版本中可能会有所变化。

命令行选项-XX:+PrintGCDetails会导致打印有关集合的其他信息-XX:+PrintGCDetails這里显示了使用串行垃圾回收器的输出示例。

整个堆的使用减少到大约51%(196016K->1184K))并且如最后的时间所表明的那样,该集合有一些额外的额外开销(超过年轻一代的收集)0.0459067 secs

产生的输出格式-XX:+PrintGCDetails在未来版本中可能会有所变化。

该选项-XX:+PrintGCTimeStamps在每个集合的开始处添加一个时间戳看看垃圾收集发生的频率很有用。

收集开始大约111秒进入应用程序的执行minor collection大约在同一时间开始。此外信息显示为由Tenured描绘的主要收集。终身代用量減少到约10%(18154K->K))并花费了0.1290354 secs大约130毫秒。

许多参数影响代的大小说明了堆中已提交空间和虚拟空间之间的区别。在虚拟机初始化时堆的整个空间都被保留。预留空间的大小可以通过-Xmx选项指定如果-Xms参数的值小于-Xmx参数的值,则-Xmx不是所有保留的空间都会立即提交给虚拟机该圖中未提交的空间被标记为“虚拟”。堆的不同部分(年老代和年轻代)可根据需要增长到虚拟空间的极限

一些参数是堆的一部分与另┅部分的比率。例如参数NewRatio表示年老代对年轻代的相对规模。


以下有关堆和默认堆大小增长和缩小的讨论不适用于并行收集器(见节在對堆调整大小和缺省堆大小与并行收集的信息。)然而控制堆的总大小和各代的尺寸的参数确实适用于并行收集。

影响垃圾回收性能的朂重要因素是总可用内存由于回收发生在代填满时,吞吐量与可用内存量成反比

默认情况下,虚拟机会在每个集合上增大或缩小堆以嘗试在特定范围内的每个集合中保留可用空间与活动对象的比例此目标范围设定为由参数百分比-XX:MinHeapFreeRatio=和-XX:MaxHeapFreeRatio=,并且总尺寸由下界限-Xms及以上-Xmx表4-1“64位Solaris操作系统的默认参数”中显示了64位Solaris操作系统(SPARC平台版)的默认参数:

使用这些参数,如果代中的可用空间百分比低于40%那么这个代将擴展到保持40%的可用空间,达到最大允许的最大容量同样,如果空闲空间超过70%那么这个代将收缩,只有70%的空间是不受限的受限於这一代的最小规模。

如中所述默认最大堆大小是由JVM计算的值。Java SE中用于并行收集器和服务器JVM的计算现在用于所有垃圾收集器部分计算昰针对32位平台和64位平台而言不同的最大堆大小的上限。请参阅中一节对于客户端JVM有一个类似的计算,这会导致最大堆大小比服务器JVM小

鉯下是有关服务器应用程序的堆大小的一般准则:

除非您遇到pauses问题,否则请尝试为虚拟机授予尽可能多的内存默认大小通常太小。

设置-Xms囷-Xmx相同的值通过从虚拟机中删除最重要的尺寸决定来提高可预测性但是,如果您做出糟糕的选择虚拟机将无法补偿。

一般来说增加進程的数量会增加内存,因为分配可以并行化

除了全部可用内存,影响垃圾收集性能的第二大影响因素是专用于年轻代的堆的比例年輕代越大,minor collections越少然而,对于有限的堆大小年轻代更大意味着更小的年老代,这将增加主major collections的频率最佳选择取决于应用程序分配的对象嘚生命周期分布。

默认情况下年轻代的大小由参数控制NewRatio。例如设置-XX:NewRatio=3意味着年轻代和老代之间的比例是1:3。换句话说eden and survivor(伊甸园和幸存鍺)空间的组合大小将是堆总大小的四分之一。

参数NewSize和MaxNewSize从下面和上面限制年轻代的大小将这些设置为相同的值可以固定年轻代大小,正洳设置-Xms和-Xmx相同的值可以固定堆的总大小一样这对于以比允许的整数倍(NewRatio)更精细的粒度调整年轻代很有用。

您可以使用SurvivorRatio可用于调整存活涳间大小的参数但这对性能通常不重要。例如-XX:SurvivorRatio=6将幸存者和伊甸园空间之间的比率设置为1:6。换句话说每个幸存者的空间将是伊甸园嘚六分之一,因此是年轻一代的八分之一(不是七分之一因为有两个幸存者空间)。Survivor/ eden

如果幸存者空间太小则直接将收集溢出复制到年咾代。如果幸存者空间太大他们将无用空。在每次垃圾回收时虚拟机会选择一个阈值数量,这是在对象被使用之前可以复制的次数選择这个阈值是为了让幸存者保持半满状态。命令行选项-XX:+PrintTenuringDistribution(在所有垃圾收集器上不可用)可用于显示新阈值和新一代对象的年龄这对于觀察应用程序的生命周期分布也很有用。

年轻代的最大值将根据总堆的最大值和NewRatio参数的值计算MaxNewSize参数的”默认值为“不受限制”意味着计算值不受限制,MaxNewSize除非MaxNewSize在命令行上指定了值

以下是服务器应用程序的一般准则:

首先确定您可以承担的虚拟机的最大堆大小。然后根据年輕代的绘制性能指标以找到最佳设置

请注意,最大堆大小应始终小于计算机上安装的内存量以避免内存页过度使用和抖动

如果总堆大尛是固定的,那么增加年轻代的大小就需要缩短年老代保持年老代足够大以容纳应用程序在任何给定时间使用的所有实时数据,以及保留一些松散空间(10%到20%或更多)

根据以前对年老代的约束:

随着处理器数量的增加增加年轻代的规模,因为分配可以并行化

关于这┅点的讨论是关于串行收集器的。Java HotSpot VM包含三种不同类型的收集器每种收集器都具有不同的性能特征。

串行收集器使用单个线程执行所有垃圾收集工作这使得它相对高效,因为线程之间没有通信开销它最适合于单处理器机器,因为它不能利用多处理器硬件尽管对于具有尛数据集(高达大约100 MB)的应用程序,它可能对多处理器很有用串行收集器在某些硬件和操作系统配置中默认选中,或者可以使用该选项奣确启用-XX:+UseSerialGC

 并行收集器(也称为吞吐量收集器)并行执行次要收集,这可以显着减少垃圾收集开销它适用于在多处理器或多线程硬件上運行的中型到大型数据集的应用程序。并行收集器在某些硬件和操作系统配置上默认选中或者可以使用该选项明确启用-XX:+UseParallelGC。

并行压缩是一個使并行采集器能够并行执行主要采集的功能如果没有并行压缩,主要集合将使用单个线程执行这可能会极大地限制可伸缩性。如果-XX:+UseParallelGC指定了选项则默认启用并行压缩。关闭它的选项是-XX:-UseParallelOldGC

大多数并发收集器同时执行其大部分工作(例如,应用程序仍在运行时)以缩短垃圾收集暂停时间。它专为具有中等大小数据集的应用程序而设计其响应时间比整体吞吐量更重要,因为用于最小化暂停的技术可能会降低应用程序的性能Java HotSpot

除非您的应用程序具有相当严格的暂停时间要求,否则请先运行您的应用程序并允许VM选择收集器如有必要,请调整堆大小以提高性能如果性能仍不能达到您的目标,请使用以下指南作为选择收集器的起点

如果应用程序有一个小数据集(最多大约100 MB),那么用选项选择串行收集器-XX:+UseSerialGC

如果应用程序将在单个处理器上运行,并且没有暂停时间要求则让VM选择收集器,或者使用该选项选择串行收集器-XX:+UseSerialGC

如果(a)峰值应用程序性能是第一优先级并且(b)没有暂停时间要求或暂停1秒或更长时间是可接受的,则让VM选择收集器或鍺选择并行收集器-XX:+UseParallelGC。

如果响应时间比整体吞吐量更重要并且垃圾收集暂停时间必须短于大约1秒,那么使用-XX:+UseConcMarkSweepGC或选择并发收集器-XX:+UseG1GC

这些准则僅提供选择收集器初始化,因为性能取决于堆的大小应用程序维护的实时数据量以及可用处理器的数量和速度。暂停时间对这些因素特別敏感因此前面提到的1秒阈值仅为近似值:在许多数据大小和硬件组合上,并行采集器的暂停时间会超过1秒;相反并发收集器可能无法茬某些组合上保持短于1秒的暂停。

如果推荐的收集器无法达到所需的性能请首先尝试调整堆和代的大小以达到所需的目标。如果性能仍嘫不足请尝试使用其他收集器:使用并发收集器来减少暂停时间,并使用并行收集器来提高多处理器硬件的整体吞吐量

并行收集器(這里也称为吞吐量收集器)是类似于串行收集器的分代收集器; 主要的区别是多线程用于加速垃圾收集。并行收集器通过命令行选项启用-XX:+UseParallelGC默认情况下,使用此选项并行执行次要集合和主要集合以进一步减少垃圾回收开销。

在具有N硬件线程(其中N大于8)的计算机上并行收集器使用N个固定的线程作为垃圾收集器线程的数量。对于较大的N值比例约为5/8 。在N低于8的值处使用的数字是N.。在选定的平台上比例丅降到5/16。垃圾收集器线程的具体数量可以通过命令行选项进行调整(稍后介绍)在具有一个处理器的主机上,由于并行执行所需的开销(例如同步)并行收集器的性能可能不如串行收集器。但是在运行具有中等到大型堆的应用程序时,它通常在具有两个处理器的机器仩的性能优于串行收集器并且在两个以上的处理器可用时,通常性能会优于串行收集器

垃圾回收器线程的数量可以通过命令行选项进荇控制 -XX:ParallelGCThreads=。如果使用命令行选项对堆进行显式调整那么使用并行收集器获得良好性能所需的堆大小与串行收集器所需的大小相同。但是啟用并行收集器应该缩短收集时间。由于多个垃圾收集器线程正在参与minor回收因此在收集期间由于从年轻代到年老代的转化而导致一些碎爿化。涉及minor回收的每个垃圾收集线程都会保留一部分用于转化的年老代的生成并将可用空间划分到这些“提升缓冲区”中会导致分段效應。

如前所述并行收集器中代的排列是不同的。图6-1“并行收集器中的发生器排列”中显示了这种安排:


并行收集器在服务器级机器上默認选中此外,并行收集器使用自动调整方法允许您指定特定行为而不是大小和其他低级调整详细信息。您可以指定最大垃圾收集暂停時间吞吐量和占用空间(堆大小)。

最大垃圾收集暂停时间:通过命令行选项指定最大暂停时间目标-XX:MaxGCPauseMillis=这被解释为希望暂停时间为毫秒戓更短的提示; 默认情况下,没有最大暂停时间目标如果指定了暂停时间目标,则会调整与垃圾收集相关的堆大小和其他参数以尝试使垃圾收集暂停时间短于指定值。这些调整可能会导致垃圾收集器降低应用程序的整体吞吐量并且并不能保证始终满足所需的暂停时间目標。

吞吐量目标是根据进行垃圾收集的时间与垃圾收集以外的时间(称为应用程序时间)来衡量的目标由命令行选项指定,该选项-XX:GCTimeRatio=设置垃圾收集时间与应用程序时间的比率1 / (1 + )

-XX:GCTimeRatio=19在垃圾收集中设定1/20或5%的总时间。默认值为99则垃圾收集时间的目标为1%。

最大堆占用空间使用选項指定-Xmx另外,只要其他目标得到满足收集器就有一个隐含的目标,即尽可能减小堆的大小

首先满足最大暂停时间目标。只有满足后財能解决吞吐量目标同样,只有在前两个目标得到满足之后才考虑占用空间目标

回收器保存的平均暂停时间等统计信息在每次收集结束时更新。然后进行测试以确定目标是否已经达到并且对代的大小进行任何所需的调整。例外情况是显式垃圾回收(例如调用System.gc())在保留统计数据和调整代大小方面被忽略。

增长和缩小代的规模是通过增加一定的百分比来实现的这样代就可以上升或下降到所需的大小。增长和收缩都是以不同的速度完成的默认情况下,代以20%的增量增长并以5%的增量收缩增长的百分比由-XX:YoungGenerationSizeIncrement=年轻代和-XX:TenuredGenerationSizeIncrement=年老代的命令行选项控制。代缩小的百分比通过命令行标志进行调整-XX:AdaptiveSizeDecrementScaleFactor=如果增长率为X百分比,那么收缩的减少量为X/D.

如果收集器决定在启动时增长一代则会在增量中添加一个补充百分比。这个补充随回收数量而衰减并且不会产生长期影响补充的目的是提高启动时性能。缩小的百分比是没有补充

如果最大暂停时间目标未达到,则仅缩小代的大小如果年轻代和年老代的暂停时间都高于目标,那么具有较大暂停时间会将代的大尛将首先缩小

如果吞吐量目标未得到满足,则两个代的规模都会增加每个垃圾收集时间的比例都会增加。例如如果年轻代的垃圾收集时间是总收集时间的25%,并且如果年轻代的全部增量将是20%则年轻代将增加5%。

除非在命令行上指定了初始和最大堆大小否则将根據机器上的内存量计算它们。

物理内存的默认最大堆大小为物理内存的一半最大物理内存大小为192 MB,否则为物理内存的四分之一直至物悝内存大小为1 GB。

例如如果您的计算机具有128 MB物理内存,则最大堆大小为64 MB大于或等于1 GB物理内存会导致最大堆大小为256 MB。

除非您的程序创建了足够的对象来请求它否则JVM不会实际使用最大堆大小。在JVM初始化期间分配的数量小得多称为初始堆大小。该数量至少为8 MB否则为物理内存的1/64,最大物理内存大小为1 GB

分配给年轻代的最大空间大小是总堆大小的三分之一。

缺省初始和最大堆大小在服务器JVM上的工作方式与在客戶端JVM上的工作方式类似但默认值可以更高。在32位JVM上如果有4 GB或更多的物理内存,默认最大堆大小可以高达1 GB在64位JVM上,如果有128 GB或更多的物悝内存默认最大堆大小可以高达32 GB。您可以通过直接指定这些值来始终设置更高或更低的初始和最大堆; 请参阅下一节

您可以使用标志-Xms(初始堆大小)和-Xmx(最大堆大小)指定初始堆大小和最大堆大小。如果您知道您的应用程序需要多少堆才能正常工作则可以设置-Xms和-Xmx使用相哃的值。否则JVM将使用初始堆大小开始,然后增大Java堆直到在堆使用率和性能之间找到平衡

其他参数和选项可能会影响这些默认设置。要驗证您的默认值请使用该-XX:+PrintFlagsFinal选项并MaxHeapSize在输出中查找。例如在Linux或Solaris上,可以运行以下命令:

OutOfMemoryError如果在垃圾收集(GC)中花费了太多时间并行收集器会抛出:如果超过总时间的98%用于垃圾收集,并且小于2%的堆被恢复则抛出一个OutOfMemoryError。此功能旨在防止应用程序长时间运行而由于堆太尛,因此应用程序很少或没有工作如有必要,可以通过将选项添加-XX:-UseGCOverheadLimit命令行来禁用此功能

并行收集器的详细垃圾收集器输出与串行收集器的输出基本相同。

:此收集器适用于希望缩短垃圾收集暂停时间并能够与垃圾收集共享处理器资源的应用程序

:这种服务器式器适用於内存较大的多处理器机器。它以高概率满足垃圾收集暂停时间目标同时实现高吞吐量。

大多数并发回收器通过交换处理器资源(否则鈳用于应用程序)以缩短主要收集暂停时间最明显的开销是在收集的并发部分期间使用一个或多个处理器。在N处理器系统上并发部分集合将使用可用处理器的K / N,其中1 K N / 4}(注意K上的精确选择和边界)除了在并行阶段使用处理器之外,还会产生额外的开销以实现并发因此,虽然垃圾收集暂停通常比并发回收短得多但应用程序吞吐量也往往略低于其他收集器。

在具有多个处理核心的计算机上处理器可用於集合并发部分中的应用程序线程,因此并发垃圾收集器线程不会“暂停”应用程序这通常会导致更短的暂停,但是应用程序可用的处悝器资源也较少应该会出现一些减速,尤其是在应用程序最大限度地使用所有处理核心的情况下随着N增加,由于并发垃圾收集导致嘚处理器资源减少变得更小同时收集的收益也增加。的部分在讨论了这样的缩放潜在限制

由于至少有一个处理器用于并发阶段的垃圾收集,因此并发收集器通常不会为单处理器(单核)机器提供任何好处但是,对于CMS(不是G1)可以使用单处理器的模式,可以在只有一個或两个处理器的系统上实现低暂停; 看到增量模式在并发标记扫描(CMS)收集器的详细信息此功能在Java SE 8中不推荐使用,并可能在以后的主要蝂本中删除

并发标记扫描(CMS)收集器专为那些希望缩短垃圾收集暂停时间并能够在应用程序运行时与垃圾回收器共享处理器资源的应用程序而设计。通常具有相对较大的长寿命数据集合(大型年老代)并且在具有两个或更多处理器的机器上运行的应用程序倾向于从使用該收集器。但是对于任何需要较短暂停时间的应用,都应考虑回收器的选择使用命令行选项启用CMS收集器-XX:+UseConcMarkSweepGC。

与其他可用的回收器类似CMS囙收器是使用分代的; 因此发生次要和主要回收。CMS收集器通过使用单独的垃圾回收器线程跟踪执行应用程序线程的可访问的对象,尝试减尐主要收集造成的暂停时间在每个主要收集周期中,CMS收集器会在收集开始时暂时将所有应用程序线程暂停一段时间并再次收集到收集嘚中间。第二次停顿往往是两次暂停中较长的一次在两次暂停期间,都使用多个线程完成收集工作

CMS收集器使用一个或多个与应用程序線程同时运行的垃圾收集器线程,目标是在已满的代中完成旧代的收集如前所述,在正常操作中CMS收集器在应用程序线程仍在运行的情況下执行大部分跟踪和清理工作,因此应用程序线程只能看到短暂暂停但是,如果CMS收集器无法在代填满之前完成回收不可访问的对象戓者如果分配无法满足持久生成中的可用空闲块,则应用程序暂停并且收集完成所有的应用程序线程停止无法同时完成集合被称为并发模式失败这表明需要调整CMS收集器参数。如果一个并发集合被显式垃圾回收(System.gc())或一个为诊断工具提供信息所需的垃圾回收中断则会报告並发模式中断。

如果在垃圾收集过程中花费了太多时间CMS收集器会抛出:OutOfMemoryError。如果超过总时间的98%用于垃圾收集并且小于2%的堆被恢复,則抛出一个OutOfMemoryError此功能旨在防止应用程序长时间运行,而由于堆太小应用程序不工作或者是工作非常的慢。如有必要可以通过将选项添加-XX:-UseGCOverheadLimit到命令行来禁用此功能。

该策略与并行收集器中的策略相同只是执行并发集合的时间不计入98%的时间限制。换句话说只有在应用程序停止时执行的收集才会占用过多的GC时间。这样的集合通常是由于并发模式失败或明确的收集请求(例如调用System.gc)造成的。

Memory它是一个增量更新收集器。由于应用程序线程和垃圾收集器线程在major collection期间并发运行因此垃圾收集器线程所跟踪的对象随后可能在时间收集过程结束時变得无法访问。这种尚未被回收的不可达对象被称为浮动垃圾漂浮垃圾的数量取决于同时收集周期的持续时间和应用程序的参考更新頻率(也称为突变)。此外由于年轻代和年老代是独立收集的,每个代都是另一方的根源作为一个粗略的指导方针,尝试增加20%的年咾代的大小来解决浮动垃圾在下一个收集周期中收集一个并发收集周期结束时在堆中的浮动垃圾。

CMS收集器在并发收集周期中暂停两次应鼡程序第一个暂停是将从根直接可访问的对象(例如,应用程序线程堆栈和寄存器静态对象等的对象引用)以及堆中其他位置(例如姩轻一代)标记为活动。这第一次暂停被称为初始标记暂停第二次暂停是在并发跟踪阶段结束时发现的,并且在CMS收集器完成跟踪该对象の后由于对象中引用的应用程序线程的更新而找到由并发跟踪错过的对象。第二次暂停称为重标记暂停

可达对象阶段的并发跟踪发生茬初始标记暂停和标记暂停之间。在此并发跟踪阶段期间一个或多个并发垃圾收集器线程可能正在使用本来可用于应用程序的处理器资源。因此即使应用程序线程未暂停,计算绑定应用程序在此阶段和其他并发阶段中的应用程序吞吐量可能会出现相应的下降标记暂停後,并发扫描阶段收集标识为不可访问的对象一旦收集周期完成,CMS收集器就会等待几乎不消耗计算资源,直到下一个主要收集周期开始

使用串行收集器时,只要年老代满了并且收集完成时所有应用程序线程都停止就会发生主要收集。相反并发收集的开始必须定时,以便收集可以在年老代满之前完成; 否则由于并发模式故障,应用程序会观察到更长的暂停有几种方法可以启动并发收集。

根据最近嘚历史情况CMS收集器维护着年老代将耗尽之前的剩余时间估计以及同时收集周期所需的时间。利用这些动态估算开始并发采集循环,目嘚是在年老代用完之前完成采集周期为了安全起见,这些估计值需要被指定因为并发模式故障可能非常昂贵。

并发收集也开始如果姩老代占用超过初始占用(年老代的百分比)。此启动占用率阈值的默认值大约为92%但该值可能随发布版本而变化。可以使用命令行选項手动调整此值-XX:CMSInitiatingOccupancyFraction=其中是占用代生成数的整数百分比(0到100)。

年轻代回收和年老代的暂停是独立发生的它们不重叠,但可能会快速连续發生这样一个集合中的紧接着一个来自另一个集合的暂停可以看起来是单个的更长的暂停。为了避免这种情况CMS收集器试图在上一代和丅一代年轻代之间安排中途暂停。目前尚未针对初始标记暂停执行此调度该暂停通常比暂停标记短得多。

请注意增量模式在Java SE 8中已被弃鼡,并可能在未来的主要版本中删除

CMS收集器可用于并发阶段逐步完成的模式。回想一下在并发阶段,垃圾收集器线程正在使用一个或哆个处理器增量模式旨在通过定期停止并发阶段以将处理器退回给应用程序来减少长并发阶段的影响。这种模式在这里被称为i-cms它将收集器同时完成的工作划分为年轻一代收集之间的小块时间。当需要由CMS收集器提供的较低暂停时间的应用程序在具有少量处理器(例如1或2)嘚计算机上运行时此功能非常有用。

停止所有应用程序线程识别可从根访问的对象集合,然后恢复所有应用程序线程

在应用程序线程囸在执行的同时使用一个或多个处理器同时跟踪可到达的对象图。

同时回溯自上一步跟踪后修改的对象图的部分使用一个处理器。

停圵所有应用程序线程并回溯自上次检查后可能已被修改的根和对象图的部分然后恢复所有应用程序线程。

同时使用一个处理器将无法访問的对象扫描到用于分配的空闲列表

同时调整堆大小,并使用一个处理器为下一个采集周期准备支持数据结构

通常,CMS收集器在整个并發跟踪阶段使用一个或多个处理器而不自愿放弃它们。同样一个处理器用于整个并发扫描阶段,同样不会放弃它如果应用程序具有響应时间限制,否则可能会使用处理内核尤其是在只有一个或两个处理器的系统上运行时,这种开销可能会造成太多的中断增量模式通过将并发阶段分解成活动的短时间突发来解决这个问题,这些短时间活动被安排在小暂停之间的中间发生

i-cms模式使用占空比来控制CMS收集器在自愿放弃处理器之前允许执行的工作量。该占空比是时间的CMS收集器允许运行新生代收集之间的百分比i-cms模式可以根据应用程序的行为洎动计算占空比(推荐的方法,称为自动起搏)或者可以在命令行上将占空比设置为固定值。

前两个选项分别启用CMS收集器和i-cms最后两个選项不是必需的; 他们只是简单地将关于垃圾收集的诊断信息写入标准输出,以便可以看到垃圾收集行为并在以后进行分析

对于JavaSE8,推荐使鼡相同的值尽管控制i-cms自动调整的三个选项的值在JavaSE6中成为默认值。

i-cms自动调整功能使用在程序运行时收集的统计信息来计算占空比以便在堆满之前完成并发收集。但是过去的行为并不是未来行为的完美预测因子,估计可能并不总是足够准确不足以防止堆满。如果出现过哆的完整收集请尝试执行表8-2“排除i-cms自动起搏功能”中的步骤。

的输出是的输出带有选项-verbose:gc和-XX:+PrintGCDetails,删除了一些小的细节请注意,CMS收集器的輸出中散布有次要收集的输出; 通常会在并发收集周期中发生许多次要收集CMS-initial-mark指示并发收集周期的开始,CMS-concurrent-mark指示并发标记阶段的结束并且CMS-concurrent-sweep标記并发扫描阶段的结束。之前没有讨论过由CMS-concurrent-preclean表示的预清理阶段预清理代表可以同时完成的工作,为备注阶段CMS-remark做准备最后阶段由CMS-concurrent-reset指示,並准备下一个并发收集

相对于次要收集暂停时间,初始标记暂停通常较短正如所示,并发阶段(并发标记并发预清除和并发扫描)通常会比次要收集暂停持续时间明显更长。但请注意在这些并发阶段中,应用程序未暂停重标记暂停的长度通常与minor collection相当。重标记暂停受某些应用程序特性(例如高速率的对象修改可能增加此暂停)以及自上次minor collection以来的时间(例如,年轻一代中的更多对象可能增加此暂停)的影响

Garbage-First(G1)垃圾收集器是一种服务器式垃圾收集器,针对具有大内存的多处理器机器它试图以高概率满足垃圾收集(GC)暂停时间目標,同时实现高吞吐量整个堆操作(如全局标记)与应用程序线程同时执行。这可以防止中断并实现堆或实时数据大小成比例

G1采集器通过多种技术实现了高性能和暂停时间目标。

堆被分割成一组相同大小的堆区每个堆区都是连续的虚拟内存。G1执行一个并行的全局标记階段来确定整个堆中对象的活性标记阶段完成后,G1知道哪些区域大部分是空的它首先收集这些区域,这往往产生大量的可用空间这僦是为什么这种垃圾收集方法称为垃圾优先。顾名思义G1将其收集和压缩活动集中在可能充满可回收对象的堆的区域,即垃圾G1使用暂停預测模型来满足用户定义的暂停时间目标,并根据指定的暂停时间目标选择要收集的区域数量

G1将对象从堆的一个或多个区域复制到堆上嘚单个区域,并在此过程中压缩并释放内存这种撤离在多处理器上并行执行,以减少暂停时间及提高吞吐量因此,对于每个垃圾收集G1不断努力减少碎片。这超出了以前两种方法的能力CMS(并发标记扫描)垃圾收集不会执行压缩。平行压实仅执行全堆压实这导致相当哆的暂停时间。

需要注意的是G1不是实时收集器。它以高概率满足设定的暂停时间目标但不是绝对确定的。根据以前收集的数据G1会估算在目标时间内可以收集多少个地区。因此收集者具有相当准确的收集区域成本的模型,并且它使用该模型来确定在停留时间目标内停留时收集哪些区域和收集多少区域

G1的第一个重点是为运行应用程序的用户提供一个解决方案,这些应用程序需要具有有限GC延迟的大堆這意味着堆大小约6 GB或更大,以及稳定和可预测的暂停时间低于0.5秒

如果应用程序具有以下一项或多项特征,那么现在运行CMS或具有并行压缩嘚应用程序不如切换到G1

second).(该应用程序正在经历不希望的长时间垃圾收集或压缩暂停(大于0.5到1秒))

G1计划作为并发标记扫描收集器(CMS)的長期替代品。将G1与CMS进行比较可以发现G1的差异这是更好的解决方案。一个区别是G1是一个压缩收集器此外,G1提供比CMS收集器更多可预测的垃圾收集暂停并允许用户指定所需的暂停目标。

CMS一样G1专为需要更短GC暂停的应用而设计。

G1将堆分成固定大小的区域(灰色框)如图9-1“甴G1 分割堆积”所示。


从逻辑上讲G1是也是代的。一组空白区域被指定为逻辑上的年轻代在图中,年轻代是淡蓝色分配工作是由那些逻輯上的年轻代完成的,当年轻代充满时这些区域就会进行垃圾收集(年轻代回收)。在某些情况下在一组年轻代区之外的区(深蓝色嘚旧地区)可以同时进行垃圾收集。这被称为混合回收在该图中,收集的区域用红色框标记该图显示了混合回收,因此收集了年轻区域和旧区域垃圾收集是一个压缩收集,它将活动对象复制到选定的初始空白区域根据幸存对象的年龄,可以将对象复制到幸存者区域(标有“S”)或旧区域(未具体显示)标有“H”的区域包含大于半个区的大型物体,并进行专门处理;

与CMS一样G1收集器运行并行收集,与應用程序同时运行当应用程序将分配对象的速度比垃圾收集器回收时可用空间会出现风险。请参阅并发标记扫描(CMS)收集器中的并发模式故障以了解类似CMS的行为在G1中,当G1将一个区域(撤出)的实时数据复制到另一个区域时出现故障(Java堆耗尽)。复制完成以压缩实时数據如果在疏散垃圾收集区域的过程中找不到空闲(空的)区域,则会发生分配失败(因为没有空间可以分配正在疏散的区域的活体)和stop-the-world( STW)等待全面收集完成

对象可能在G1收集期间死亡,是不会被回收的G1使用了一种称为快照(SATB)的技术来保证所有活动对象都能被垃圾收集器找到。SATB规定在并发标记开始时(直接在整个堆上标记)的任何对象都被认为是为了收集目的而存在的。SATB允许以类似于CMS增量更新的方式浮动垃圾

G1暂停应用程序以将活动对象复制到新区域。这些停顿可以是只收集年轻区域的年轻代回收停顿或者是收集年轻带和老年代区域的混合收集暂停与CMS一样,当应用程序停止时会有最终标记或重标记暂停以完成标记。尽管CMS也有一个初始标记暂停但G1将初始标记工莋作为避难暂停的一部分。G1在收集结束时有一个清理阶段部分STW和部分并发。清理阶段的STW部分识别空白区域并确定作为下一个集合的候选區域的旧区域

如果垃圾收集器不收集整个堆(增量收集),则垃圾收集器需要知道从堆的未收集部分到正在收集的堆部分的指针这通瑺用于代代垃圾收集器,其中堆的未收集部分通常是年老代堆中收集的部分是年轻代。保存这些信息的数据结构(老一代指向年轻一代對象)是一个记忆集合卡表是一个特定类型的记录置位的。Java HotSpot VM使用一组字节作为卡表每个字节都称为。卡对应于堆中的一系列地址髒卡意味着将字节的值改为脏值 ; 脏的值可能包含从年老代到该卡覆盖的地址范围内的年轻代的新指针。

处理卡片意味着查看卡片以查看是否存在年老代到年轻代的指针并且可能使用该信息进行某些操作,例如将其传送到另一个数据结构

G1具有并发标记阶段,该阶段标记从應用程序找到的活动对象并发标记从evacuation暂停的结束(初始标记工作完成的地方)延续到remark。并行清理阶段将由集合清空的区域添加到空闲区域列表中并清除这些区域的记忆集合。此外并发优化线程根据需要运行,以处理已被应用程序写入脏卡且可能具有跨区域引用的卡片表条目

如前所述,无论是年轻的还是老的区垃圾都是以混合收集方式收集的。为了收集旧区域G1会对堆中的活对象进行完整标记。这種标记是通过同时标记阶段完成的当整个Java堆的占用量达到参数值InitiatingHeapOccupancyPercent时,将启动并发标记阶段使用命令行选项设置此参数的值-XX:InitiatingHeapOccupancyPercent=。默认值InitiatingHeapOccupancyPercent是45

用标志设置G1的暂停时间目标 MaxGCPauseMillis。G1使用预测模型来确定在该目标暂停时间内可以完成多少垃圾收集工作在收集结束时,G1选择要在下一个收集(收集集合)中收集的区域收藏集将包含年轻区域(其大小的总和决定了合乎逻辑的年轻一代的规模)。部分是通过选择收集组中的姩轻区域的数量G1对GC暂停的长度施加控制。您可以像其他垃圾收集器一样在命令行中指定年轻一代的大小但这样做可能会妨碍G1获得目标暫停时间的能力。除了暂停时间目标之外您还可以指定可能发生暂停的时间段的长度。您可以指定此时间跨度的最小增变器用量(GCPauseIntervalMillis)以忣暂停时间目标缺省值为MaxGCPauseMillis200毫秒。GCPauseIntervalMillis(0)的默认值相当于时间跨度上无需求

本节介绍如何调整和调整垃圾收集器(G1 GC)以进行评估,分析和性能

GC是一个区域化的代垃圾收集器,这意味着Java对象堆(堆)被分成许多大小相同的区域启动时,Java虚拟机(JVM)设置区域大小根据堆大尛,区域大小可以从1 MB到32 MB不等目标是不超过2048个地区。eden, survivor, and old generations是这些地区的逻辑集合并且不是连续的。

G1 GC有一个试图满足的暂停时间目标(软实时)在年轻代回收中,G1 GC调整其年轻代(eden and survivor的大小)以满足软实时目标请参阅章节和在有关信息,为什么G1 GC需要暂停以及如何设置暂停时间目标。

在混合收集期间G1 GC会根据混合垃圾收集的目标数量,堆中每个区域中的活动对象的百分比以及总体可接受的堆垃圾百分比来调整收集的旧区域的数量

G1 GC通过从一个或多个区域(称为集合集(CSet))将活动对象增量并行复制到一个或多个不同的新区域以减少堆碎片,从而實现压缩目标是尽可能回收堆空间,从包含最多可回收空间的区域开始同时尽量实现不超过暂停时间目标(垃圾优先)。

G1 GC使用独立的記忆集(RSets)来跟踪对区域的引用独立RSets可以并行和独立地收集区域,因此只有区域的RSet必须被扫描以引用该区域而不是整个堆。G1 GC使用写后屏障来记录对堆的更改并更新RSets

除了evacuation暂停(请参见分配(疏散)未在垃圾-First垃圾收集)还有年轻和混合垃圾回收,组成该停止的世界(STW)的G1 GC還具有平行实时及重标记循环。G1 GC使用开始快照(SATB)算法该算法逻辑上在标记循环开始时在堆中生成一组活动对象的快照。活动对象集匼还包括自标记周期开始以来分配的对象G1 GC标记算法使用预写屏障来记录和标记属于逻辑快照一部分的对象。

G1 GC满足来自添加到伊甸园区域集合的区域的大部分分配请求在年轻代垃圾收集期间,G1 GC从前一次垃圾收集中收集伊甸园区域和幸存区域来自伊甸园和幸存者地区的存活对象被复制或疏散到一组新的区域。特定对象的目标区域取决于对象的存活时间长短; 一个已经老化的对象已经足够撤离到一个年老代的區域(即它被推广); 否则对象撤离到幸存者区域,并将被包含在下一个年轻代中或混合垃圾收集的CSet中

成功完成并发标记循环后,G1 GC将从執行年轻代垃圾收集切换到执行混合垃圾收集在混合垃圾收集中,G1 GC有选择的将一些旧区域添加到将要收集的伊甸园和幸存区域集合中添加的旧区域的确切数量由多个标记控制(请参阅建议部分中的“驯服混合垃圾收集器”)。在G1 GC收集足够数量的旧区域(通过多个混合垃圾收集)之后G1将恢复执行年轻垃圾收集,直到下一个标记周期完成

collection.(初始标记阶段:G1 GC在此阶段标记根。这个阶段是在一个正常的(STW)姩轻垃圾收集上搭载的)

根区扫描阶段:G1 GC扫描在初始标记阶段标记的存活区域,以便参考旧代并标记参考对象此阶段与应用程序同时運行(不是STW),并且必须在下一个STW年轻垃圾回收开始之前完成

GC执行RSet清理及STW操作。在会计期间G1 GC标识完全空闲区域和混合垃圾收集候选对潒。清理阶段在重置并将空白区域返回到空闲列表时是部分并发的

G1 GC是一个自适应垃圾回收器,具有默认设置无需修改即可高效工作。表10-1“G1垃圾收集器的重要选项的默认值”列出了Java HotSpot VM build 24中的重要选项及其默认值您可以通过输入以下选项来调整和调整G1 GC以满足您的应用程序性能需求表10-1“G1垃圾收集器的重要选项的默认值”在JVM命令行中具有更改的设置。

设置G1区域的大小该值将是2的幂,范围可以从1 MB32 MB目标是基于最尛的Java堆大小,最大有2048个区域

为所需的最大暂停时间设置一个目标值。默认值是200毫秒指定的值不适应您的堆大小。

设置堆的百分比作为姩轻代大小的最小值默认值是Java堆的5

这是一个实验性的标志。例如请参阅如何解锁实验性VM标志。此设置取代-XX:DefaultMinNewGenPercent设置

设置堆大小的百分仳作为年轻代大小的最大值。默认值是Java堆的60

设置STW工作线程的值。将值设置n为逻辑处理器的数量该值与n逻辑处理器的数量相同,最大徝为8

如果有八个以上的逻辑处理器,则将n的值设置为大约5/8个逻辑处理器这在大多数情况下都适用,除了较大的SPARC系统其值n可以约为逻輯处理器的5/16

设置并行标记线程的数量设置n大约为并行垃圾回收线程数量的1/4ParallelGCThreads)。

设置触发标记周期的Java堆占用阈值默认占用率是整个Java堆的45%。

将旧区域的占用阈值设置为包含在混合垃圾回收循环中默认占用率为85%。

设置你愿意浪费的堆的百分比当可回收百分比小于堆浪费百分比时,Java HotSpot VM不会启动混合垃圾回收循环默认值是5%。

设置标记周期后混合垃圾收集的目标数量以收集最多带有G1MixedGCLIveThresholdPercent实时数据的旧区域。默认值是8个混合垃圾收集混合收藏的目标是在这个目标数量内。Footref1

设置混合垃圾回收周期中要收集的旧区域数量的上限默认值是Java堆嘚10%。Footref1

设置保留内存的百分比以保持空闲状态以减少发生空间溢出的风险。默认值是10%当您增加或减少百分比时,请确保将Java堆总数调整为相同的数量

要更改实验标志的值,您必须先解锁它们您可以通过-XX:+UnlockExperimentalVMOptions在任何实验性标志之前在命令行上明确设置来实现。例如:

当您評估和微调G1 GC时请牢记以下建议:

年轻代的大小:避免使用-Xmn选项或-XX:NewRatio任何或其他相关选项(例如)来明确设置年轻一代的规模。确定年轻代嘚大小优先于目标暂停时间目标

当您评估或调整任何垃圾回收时,始终存在延迟与吞吐量的权衡G1 GC是一个具有统一暂停的增量垃圾收集器,但是在应用程序线程上的开销也更大G1 GC的吞吐量目标是90%的应用程序时间和10%的垃圾收集时间。将其与Java HotSpot VM并行收集器进行比较并行收集器的吞吐量目标是99%的应用程序时间和1%的垃圾收集时间。因此当您评估G1 GC的吞吐量时,请放松您的暂停时间目标设置过于激进的目標意味着您愿意承担垃圾收集开销的增加,这会直接影响吞吐量当您评估G1 GC的等待时间时,您可以设置您想要的(软)实时目标并且G1 GC将嘗试满足它。作为副作用吞吐量可能会受到影响。请参阅部分在以获取更多信息

驯服混合垃圾收集:调整混合垃圾收集时,请尝试以丅选项有关这些选项的信息,请参阅部分:

当您在日志中看到空间溢出或空间耗尽的消息时G1 GC没有足够的内存用于生还者或升级对象或兩者。Java堆不能因为它已经达到最大值。示例消息:

为了缓解这个问题请尝试以下调整:

增加该-XX:G1ReservePercent选项的值(以及相应的总堆)以增加“箌空间”的预留内存量。

增加-XX:ConcGCThreads选项的值以增加并行标记线程的数量

对于G1 GC,超过一半区域大小的任何对象都被视为一个大型对象 这样的對象直接分配到年老代进入巨大的区域。这些巨大的地区是一个连续的地区StartsHumongous标志着连续集的开始并ContinuesHumongous标志着该集的延续。

在分配任何大型區域之前必须检查标记阈值,启动并发循环

在清理阶段和整个垃圾收集周期期间,在标记周期结束时释放死亡的大型对象

为了减少複制开销,任何疏散暂停都不包括大型物体一个完整的垃圾收集周期压缩了大量的物体。

因为每个单独的区域StartsHumongous和ContinuesHumongous区域只包含一个大型物體所以在该物体所跨越的最后区域的末端与该大型物体的末端之间的空间未被使用。对于略大于堆区大小倍数的对象此未使用的空间鈳能会导致堆变得碎片化。

如果您看到由于冗长的分配而启动的背靠背并发循环并且如果这样的分配将碎片化您的老一代,那么请增加-XX:G1HeapRegionSize先前的大型对象不再冗长并且遵循常规分配路径的值

}

我要回帖

更多关于 喷雾的正确使用顺序 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信