从Jdk8到Jdk12的Java虚拟机垃圾回收(垃圾收集)相关论文和官方网站集锦

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/21aspnet/article/details/88772421

这张图画的很清晰

出自:http://jprante.github.io/2012/11/28/Elasticsearch-Java-Virtual-Machine-settings-explained.html

JDK12的JVM选项

Java虚拟机技术概述

本章介绍Java虚拟机(JVM)的实现以及Java HotSpot技术的主要功能:

  • 自适应编译器:标准解释器用于启动应用程序。应用程序运行时,将分析代码以检测性能瓶颈或热点。Java HotSpot VM编译代码的性能关键部分以提高性能,但不编译很少使用的代码(大多数应用程序)。Java HotSpot VM使用自适应编译器来决定如何使用内联等技术优化编译代码。
  • 快速内存分配和垃圾收集:Java HotSpot技术为对象和快速,高效,最先进的垃圾收集器提供快速内存分配。
  • 线程同步:Java HotSpot技术提供了一种线程处理功能,旨在扩展以用于大型共享内存多处理器服务器。

在Oracle Java Runtime Environment(JRE)8及更早版本中,JVM的不同实现(客户端VM,服务器VM和最小VM)支持常用作客户端,服务器和嵌入式系统的配置。由于大多数系统现在可以利用服务器VM,因此Oracle Java运行时环境(JRE)9仅提供该VM实现。

Java虚拟机指南

垃圾收集调整

垃圾收集

Oracle的HotSpot VM包含几个垃圾收集器,可用于帮助优化应用程序的性能。如果您的应用程序处理大量数据(多个千兆字节),具有多个线程并具有高事务率,则垃圾收集器尤其有用。

有关可用垃圾收集器的说明,请参阅Java平台标准版HotSpot虚拟机垃圾收集调整指南中的垃圾收集实现

G1与其他收集器(CMS)的比较

这是G1和其他收集器之间主要差异的总结:

  • 并行GC只能作为一个整体压缩和回收旧一代的空间。G1逐步将这项工作分散到多个更短的集合中。这大大缩短了暂停时间,可能会降低吞吐量。
  • 与CMS类似,G1同时执行旧一代空间回收的一部分。但是,CMS无法对旧一代堆进行碎片整理,最终会遇到长的Full GC。
  • G1可能表现出比上述收集器更高的开销,由于其并发性质而影响吞吐量。
  • ZGC针对非常大的堆,旨在以更高的吞吐量成本提供显着更小的暂停时间。

已经不推荐使用CMS推荐G1了: 

Java虚拟机规范,Java SE 12 Edition

JDK8的JVM选项

Java虚拟机规范,Java SE 8 Edition

https://docs.oracle.com/javase/8/docs/technotes/tools/windows/toc.html

JVM按以下顺序搜索并加载类:

Bootstrap类,它们是构成Java平台的类,包括类rt.jar和其他几个重要的JAR文件。

扩展类,它使用Java扩展机制。这些类捆绑为JAR文件并位于extensions目录中。

用户类,是由开发人员和第三方定义的类,不利用扩展机制。您-classpath可以使用命令行(首选)上的选项或CLASSPATH环境变量来标识这些类的位置。请参阅设置类路径。

----------------------

https://docs.oracle.com/javase/8/docs/technotes/tools/windows/java.html#CBBIJCHG

下面选择一些常用选项,更多完整参数建议看官方链接:

-XX:MaxGCPauseMillis = 时间

设置最大GC暂停时间的目标(以毫秒为单位)。这是一个软目标,JVM将尽最大努力实现它。默认情况下,没有最大暂停时间值。

以下示例显示如何将最大目标暂停时间设置为500毫秒:

-XX:MaxGCPauseMillis = 500

-XX:MaxMetaspaceSize = size

设置可以为类元数据分配的最大本机内存量默认情况下,大小不受限制。应用程序的元数据量取决于应用程序本身,其他正在运行的应用程序以及系统上可用的内存量。

以下示例显示如何将最大类元数据大小设置为256 MB:

-XX:MaxMetaspaceSize =256M

-XX:ParallelGCThreads = threads

设置在年轻和老一代中用于并行垃圾收集的线程数。默认值取决于JVM可用的CPU数量

例如,要将并行GC的线程数设置为2,请指定以下选项:

-XX:ParallelGCThreads = 2

-XX:+ ScavengeBeforeFullGC

在每个完整GC之前启用年轻代的GC。默认情况下启用此选项。Oracle建议您不要禁用它,因为在完整GC之前清除年轻代可以减少从旧代空间到年轻代空间可到达的对象数。要在每个完整GC之前禁用年轻代的GC,请指定-XX:-ScavengeBeforeFullGC

-XX:+ UseTLAB

允许在年轻代空间中使用线程局部分配块(TLAB)。默认情况下启用此选项。要禁用TLAB,请指定-XX:-UseTLAB

-XX:TLABSize = size

设置线程局部分配缓冲区(TLAB)的初始大小(以字节为单位)。附加字母kK表示千字节,mM指示兆字节,gG指示千兆字节。如果此选项设置为0,则JVM会自动选择初始大小。

以下示例显示如何将初始TLAB大小设置为512 KB:

-XX:TLABSize = 512K

-XX:+ UseG1GC

允许使用垃圾优先(G1)垃圾收集器。它是一个服务器式垃圾收集器,针对具有大量RAM的多处理器计算机。它以高概率满足GC暂停时间目标,同时保持良好的吞吐量。G1收集器推荐用于需要大堆(大小约为6 GB或更大)且GC延迟要求有限的应用(稳定且可预测的暂停时间低于0.5秒)。

默认情况下,禁用此选项,并根据计算机的配置和JVM的类型自动选择收集器。

XX:+ UseConcMarkSweepGC

允许为旧一代使用CMS垃圾收集器。Oracle建议您在spam(-XX:+UseParallelGC)垃圾收集器无法满足应用程序延迟要求时使用CMS垃圾收集器。G1垃圾收集器(-XX:+UseG1GC)是另一种选择。

默认情况下,禁用此选项,并根据计算机的配置和JVM的类型自动选择收集器。启用此选项后,将-XX:+UseParNewGC自动设置该选项,您不应禁用该选项,因为JDK 8中已弃用以下选项组合:-XX:+UseConcMarkSweepGC -XX:-UseParNewGC

 

-XX:+ PrintGC

允许在每个GC上打印消息。默认情况下,禁用此选项。

======================

JDK7的JVM选项

https://www.oracle.com/technetwork/articles/java/vmoptions-jsp-140102.html

-------------------------------

Java垃圾收集基础知识

G1垃圾收集器入门

------------------------------

如果还看不明白这个说的比较清晰准确可以入门看看:

JVM 垃圾回收机制

JVM GC参数以及GC算法的应用 

上文同《JVM中的G1垃圾回收器

G1虽然保留了CMS关于代的概念,但是代已经不是物理上连续区域,而是一个逻辑的概念。在标记过程中,每个区域的对象活性都被计算,在回收时候,就可以根据用户设置的停顿时间,选择活性较低的区域收集,这样既能保证垃圾回收,又能保证停顿时间,而且也不会降低太多的吞吐量。Remark阶段新算法的运用,以及收集过程中的压缩,都弥补了CMS不足。引用Oracle官网的一句话:“G1 is planned as the long term replacement for the Concurrent Mark-Sweep Collector (CMS)”。

-----

什么时候会发生FullGC

 

使用CMS垃圾收集器产生的问题和解决方案

首先我们经常遇到promotion failed问题,这也确实是个很头痛的问题,一般是进行Minor GC的时候,发现救助空间不够,所以,需要移动一些新生带的对象到老年带,然而,有些时候尽管老年带有足够的空间,但是由于CMS采用标记清除算法,默认并不使用标记整理算法,可能会产生很多碎片,因此,这些碎片无法完成大对象向老年带转移,因此需要进行CMS在老年带的Full GC来合并碎片。

这个问题的直接影响就是它会导致提前进行CMS Full GC, 尽管这个时候CMS的老年带并没有填满,只不过有过多的碎片而已,但是Full GC导致的stop-the-wold是难以接受的。

解决这个问题的办法就是可以让CMS在进行一定次数的Full GC(标记清除)的时候进行一次标记整理算法,CMS提供了以下参数来控制:

-XX:UseCMSCompactAtFullCollection -XX:CMSFullGCBeforeCompaction=5

也就是CMS在进行5次Full GC(标记清除)之后进行一次标记整理算法,从而可以控制老年带的碎片在一定的数量以内,甚至可以配置CMS在每次Full GC的时候都进行内存的整理。

另外,有些应用存在比较大的对象朝生熄灭,这些对象在救助空间无法容纳,因此,会提早进入老年带,老年带如果有碎片,也会产生promotion failed, 因此我们应该控制这样的对象在新生代,然后在下次Minor GC的时候就被回收掉,这样避免了过早的进行CMS Full GC操作,下面的一个配置样例就通过增加救助空间的大小来解决这个问题:

-Xmx4000M -Xms4000M -Xmn600M -XXmSize=500M -XX:MaxPermSize=500M -Xss256K -XX:+DisableExplicitGC -XX:SurvivorRatio=1 -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:+CMSParallelRemarkEnabled eCMSCompactAtFullCollection -XX:CMSFullGCsBeforeCompaction=0 -XX:+CMSClassUnloadingEnabled -XX:LargePageSizeInBytes=128M -XX:+UseFastAccessorMethods -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=80 -XX:SoftRefLRUPolicyMSPerMB=0 -XX:+PrintClassHistogram -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintHeapAtGC -Xloggc:log/gc.log

上面讨论了promotion failed引起的原因以及解决方案,除了promotion failed还有一个情况会引起CMS回收失败,从而退回到Serial Old收集器进行回收,我们在线上尤其要注意的是concurrent mode failure出现的频率,这可以通过-XX:+PrintGCDetails来观察,当出现concurrent mode failure的现象时,就意味着此时JVM将继续采用Stop-The-World的方式来进行Full GC,这种情况下,CMS就没什么意义了,造成concurrent mode failure的原因是当minor GC进行时,旧生代所剩下的空间小于Eden区域+From区域的空间,或者在CMS执行老年带的回收时有业务线程试图将大的对象放入老年带,导致CMS在老年带的回收慢于业务对象对老年带内存的分配。

解决这个问题的通用方法是调低触发CMS GC执行的阀值,CMS GC触发主要由CMSInitiatingOccupancyFraction值决定,默认情况是当旧生代已用空间为68%时,即触发CMS GC,在出现concurrent mode failure的情况下,可考虑调小这个值,提前CMS GC的触发,以保证旧生代有足够的空间。

总结:

1. promotion failed – concurrent mode failure

Minor GC后, 救助空间容纳不了剩余对象,将要放入老年带,老年带有碎片或者不能容纳这些对象,就产生了concurrent mode failure, 然后进行stop-the-world的Serial Old收集器。

解决办法:-XX:UseCMSCompactAtFullCollection -XX:CMSFullGCBeforeCompaction=5 或者 调大新生代或者救助空间

2. concurrent mode failure

CMS是和业务线程并发运行的,在执行CMS的过程中有业务对象需要在老年带直接分配,例如大对象,但是老年带没有足够的空间来分配,所以导致concurrent mode failure, 然后需要进行stop-the-world的Serial Old收集器。

解决办法:+XX:CMSInitiatingOccupancyFraction,调大老年带的空间,+XX:CMSMaxAbortablePrecleanTime

总结一句话:使用标记整理清除碎片和提早进行CMS操作。

----------------------------------------------------------------

JVM性能优化,第1部分:JVM技术入门

JVM性能优化,第2部分:编译器

JVM性能优化,第4部分:针对低延迟的C4垃圾收集......

JVM性能优化,第3部分:垃圾收集

 

http://ssw.jku.at/General/Staff/TW/igv.html

IdealGraphVisualizer研究C2的实用工具之一

使用 Ideal Graph Visualizer 分析编译代码过程 

-------------------

https://www.cs.kent.ac.uk/people/staff/rej/gcbib/

----------------- 

https://hllvm-group.iteye.com/group/topic/21468 

RednaxelaFX的博客

RednaxelaFX 2010-09-11

关于VM的帖的目录 

------

Vladimir Ivanov讲解JIT编译器: 
JIT-compiler in JVM seen by a Java developer, Vladimir Ivanov, JavaOne 2013 Moscow, 2013 

https://wiki.openjdk.java.net/display/HotSpot/Garbage+Collection 

[HotSpot VM] 请教G1算法的原理 

至于G1的算法⋯大体概念其实还挺直观的?到底是哪里没明白? 

从最高层看,G1的collector一侧其实就是两个大部分: 
* 全局并发标记(global concurrent marking) 
* 拷贝存活对象(evacuation) 
而这两部分可以相对独立的执行。 

Global concurrent marking基于SATB形式的并发标记。它具体分为下面几个阶段: 
1、初始标记(initial marking):暂停阶段。扫描根集合,标记所有从根集合可直接到达的对象并将它们的字段压入扫描栈(marking stack)中等到后续扫描。G1使用外部的bitmap来记录mark信息,而不使用对象头的mark word里的mark bit。在分代式G1模式中,初始标记阶段借用young GC的暂停,因而没有额外的、单独的暂停阶段。 
2、并发标记(concurrent marking):并发阶段。不断从扫描栈取出引用递归扫描整个堆里的对象图。每扫描到一个对象就会对其标记,并将其字段压入扫描栈。重复扫描过程直到扫描栈清空。过程中还会扫描SATB write barrier所记录下的引用。 
3、最终标记(final marking,在实现中也叫remarking):暂停阶段。在完成并发标记后,每个Java线程还会有一些剩下的SATB write barrier记录的引用尚未处理。这个阶段就负责把剩下的引用处理完。同时这个阶段也进行弱引用处理(reference processing)。 
注意这个暂停与CMS的remark有一个本质上的区别,那就是这个暂停只需要扫描SATB buffer,而CMS的remark需要重新扫描mod-union table里的dirty card外加整个根集合,而此时整个young gen(不管对象死活)都会被当作根集合的一部分,因而CMS remark有可能会非常慢。 
4、清理(cleanup):暂停阶段。清点和重置标记状态。这个阶段有点像mark-sweep中的sweep阶段,不过不是在堆上sweep实际对象,而是在marking bitmap里统计每个region被标记为活的对象有多少。这个阶段如果发现完全没有活对象的region就会将其整体回收到可分配region列表中。 

Evacuation阶段是全暂停的。它负责把一部分region里的活对象拷贝到空region里去,然后回收原本的region的空间。 
Evacuation阶段可以自由选择任意多个region来独立收集构成收集集合(collection set,简称CSet),靠per-region remembered set(简称RSet)实现。这是regional garbage collector的特征。 
在选定CSet后,evacuation其实就跟ParallelScavenge的young GC的算法类似,采用并行copying(或者叫scavenging)算法把CSet里每个region里的活对象拷贝到新的region里,整个过程完全暂停。从这个意义上说,G1的evacuation跟传统的mark-compact算法的compaction完全不同:前者会自己从根集合遍历对象图来判定对象的生死,不需要依赖global concurrent marking的结果,有就用,没有拉倒;而后者则依赖于之前的mark阶段对对象生死的判定。 

论文里提到的纯G1模式下,CSet的选定完全靠统计模型找处收益最高、开销不超过用户指定的上限的若干region。由于每个region都有RSet覆盖,要单独evacuate任意一个或多个region都没问题。 

分代式G1模式下有两种选定CSet的子模式,分别对应young GC与mixed GC: 
* Young GC:选定所有young gen里的region。通过控制young gen的region个数来控制young GC的开销。 
* Mixed GC:选定所有young gen里的region,外加根据global concurrent marking统计得出收集收益高的若干old gen region。在用户指定的开销目标范围内尽可能选择收益高的old gen region。 
可以看到young gen region总是在CSet内。因此分代式G1不维护从young gen region出发的引用涉及的RSet更新。 

分代式G1的正常工作流程就是在young GC与mixed GC之间视情况切换,背后定期做做全局并发标记。Initial marking默认搭在young GC上执行;当全局并发标记正在工作时,G1不会选择做mixed GC,反之如果有mixed GC正在进行中G1也不会启动initial marking。 
在正常工作流程中没有full GC的概念,old gen的收集全靠mixed GC来完成。 

如果mixed GC实在无法跟上程序分配内存的速度,导致old gen填满无法继续进行mixed GC,就会切换到G1之外的serial old GC来收集整个GC heap(注意,包括young、old、perm)。这才是真正的full GC。Full GC之所以叫full就是要收集整个堆,只选择old gen的部分region算不上full GC。进入这种状态的G1就跟-XX:+UseSerialGC的full GC一样(背后的核心代码是两者共用的)。 
顺带一提,G1 GC的System.gc()默认还是full GC,也就是serial old GC。只有加上 -XX:+ExplicitGCInvokesConcurrent 时G1才会用自身的并发GC来执行System.gc()——此时System.gc()的作用是强行启动一次global concurrent marking;一般情况下暂停中只会做initial marking然后就返回了,接下来的concurrent marking还是照常并发执行。 

然后G1在mutator一侧需要使用write barrier来实现: 
* SATB snapshot的完整性 
* 跨region的引用记录到RSet里。 
这两个动作都使用了logging barrier,其处理有一部分由collector一侧并发执行。 

可以看到在这么多步骤里,G1只有两件事是并发执行的:(1) 全局并发标记;(2) logging write barrier的部分处理。而“拷贝对象”(evacuation)这个很耗时的动作却不是并发而是完全暂停的。那G1为何还可以叫做低延迟的GC实现呢? 
重点就在于G1虽然会mark整个堆,但并不evacuate所有有活对象的region;通过只选择收益高的少量region来evacuate,这种暂停的开销就可以(在一定范围内)可控。每次evacuate的暂停时间应该跟一般GC的young GC类似。所以G1把自己标榜为“软实时”(soft real-time)的GC。 

但是毕竟要暂停来拷贝对象,这个暂停时间再怎么低也有限。G1的evacuation pause在几十到一百甚至两百毫秒都很正常。所以切记不要把 -XX:MaxGCPauseMillis 设得太低,不然G1跟不上目标就容易导致垃圾堆积,反而更容易引发full GC而降低性能。通常设到100ms、250ms之类的都可能是合理的。设到50ms就不太靠谱,G1可能一开始还跟得上,跑的时间一长就开始乱来了。 
这也提醒大家:如果您的程序要长时间运行,那么在技术选型评估GC性能的时候要让测试程序跑足够长时间才能看清状况。多久才够长取决于实际应用要连续运行多久。不然一个要运行一个月才重启一次的程序,如果测试的时候只测了两个小时就觉得没问题,实际上线跑起来可能正好两个半小时的时候来了一次几分钟的full GC暂停,那就纱布了⋯ 

G1需要暂停来拷贝对象,而CMS在暂停中只需要扫描(mark)对象,那算法上G1的暂停时间会比CMS短么? 
其实CMS在较小的堆、合适的workload的条件下暂停时间可以很轻松的短于G1。在2011年的时候Ramki告诉我堆大小的分水岭大概在10GB~15GB左右:以下的-Xmx更适合CMS,以上的才适合试用G1。现在到了2014年,G1的实现经过一定调优,大概在6GB~8GB也可以跟CMS有一比,我之前见过有在-Xmx4g的环境里G1比CMS的暂停时间更短的案例。 
合适的workload:CMS最严重的暂停通常发生在remark阶段,因为它要扫描整个根集合,其中包括整个young gen。如果在CMS的并发标记阶段,mutator仍然在高速分配内存使得young gen里有很多对象的话,那remark阶段就可能会有很长时间的暂停。Young gen越大,CMS remark暂停时间就有可能越长。所以这是不适合CMS的workload。相反,如果mutator的分配速率比较温和,然后给足时间让并发的precleaning做好remark的前期工作,这样CMS就只需要较短的remark暂停,这种条件下G1的暂停时间很难低于CMS。 

要在拷贝对象的前提下实现真正的低延迟就需要做并发拷贝(concurrent compaction)。但是现在已知的实现concurrent compaction的GC算法无一例外需要使用某种形式的read barrier,例如Azul的C4和Red Hat的Shenendoah。不用read barrier的话,没办法安全的实现一边移动对象一边修正指向这些对象的引用,因为mutator也可以会并发的访问到这些引用。 
而G1则坚持只用write barrier不用read barrier,所以无法实现concurrent compaction。 

大体概念其实就这样。有许多细节是挺麻烦的,例如如何提高并发减少瓶颈,如何处理收集到一半需要提前终止(abort,例如evacuation failure)的情况,等等。这样在读源码的时候会很头疼,但只是理解大体概念不需要关心到那种细节。 

其实影响G1实际性能的许多地方都在细节里,而不在基本算法上。例如整个开销-收益模型,收集时机的预测模型,选取CSet的策略等等。影响用户对G1做性能调优的也是在这些地方。可惜现在的G1在这些细节上做得仍然不算很好,所以预测得不够准确,性能潜力还无法完全发挥。我每天听同事吐槽感到甚欢乐orz 

[资料] 名词链接帖[占位]   https://rednaxelafx.iteye.com/

新生代回收调试的一些心得    了解CMS GC日志

输出Java程序| 第10集(垃圾收集)

如何使对象符合Java中的垃圾收集条件?

如何防止Java中的垃圾收集类的对象

Mark-and-Sweep:垃圾收集算法

Iterator vs Java中的集合

选择合适的GC

G1垃圾收集器

Java生态系统的好消息是,从JDK 9开始,默认情况下启用现代缩小的G1垃圾收集器。如果使用较低版本的JDK,则可以使用该-XX:+UseG1GC 参数启用G1  。

G1的主要优势之一是能够在没有冗长的暂停时间的情况下压缩可用内存空间。它也可以取消使用未使用的堆。我们发现此GC是在OpenJDK或HotSpot JDK上运行的Java应用程序的垂直扩展的最佳选择。

为了更好地理解JVM在不同内存压力水平下的行为,我们将运行三种情况:

  1. 快速内存使用量增长。

  2. 中等内存使用量增长。

  3. 内存使用量增长缓慢。

垃圾收集器 - 串行与并行与CMS与G1(以及Java 8中的新功能) 

Java 8和G1收集器

使用Java 8更新20的另一个漂亮的优化是G1收集器字符串重复数据删除。由于字符串(及其内部char []数组)占用了我们的大部分堆,因此进行了一项新的优化,使G1收集器能够识别在堆中多次复制的字符串,并将它们更正为指向相同的内部字符串[]数组,以避免相同字符串的多个副本在堆内无效地驻留。您可以使用-XX:+ UseStringDeduplication JVM参数来尝试此操作。

Java 8和PermGen

Java 8中最大的变化之一是  删除传统上为类元数据,实体字符串和静态变量分配的堆的permgen部分。传统上,这需要开发人员使用能够加载大量类的应用程序(使用企业容器的应用程序常见的东西)来专门优化和调整堆的这一部分。多年来,这已成为许多OutOfMemory异常的来源,因此如果JVM(大多数情况下)是一个非常好的补充,那么让它(大多数情况下)要小心。即便如此,这本身可能不会减少开发人员将他们的应用程序分离到多个JVM的浪潮。

JVM: CMS过程中的promotion failure和concurrent mode failure有何区别,如何应对

1、promotion failure,是在minor gc过程中,survivor的剩余空间不足以容纳eden及当前在用survivor区间存活对象,只能将容纳不下的对象移到年老代(promotion),而此时年老代满了无法容纳更多对象,通常伴随full gc,因而导致的promotion failure。这种情况通常需要增加年轻代大小,尽量让新生对象在年轻代的时候尽量清理掉。
2、concurrent mode failure,主要是由于cms的无法处理浮动垃圾(Floating Garbage)引起的。这个跟cms的机制有关。cms的并发清理阶段,用户线程还在运行,因此不断有新的垃圾产生,而这些垃圾不在这次清理标记的范畴里头,cms无法再本次gc清除掉,这些就是浮动垃圾。由于这种机制,cms年老代回收的阈值不能太高,否则就容易预留的内存空间很可能不够(因为本次gc同时还有浮动垃圾产生),从而导致concurrent mode failure发生。可以通过-XX:CMSInitiatingOccupancyFraction的值来调优。

垃圾收集器 - 串行与并行与CMS垃圾收集器 - 串行与并行与CMS与G1(以及Java 8中的新功能)与G1(以及Java 8中的新

 用于JVM性能调整的Java命令行选项

-XX:SurvivorRatio = <N>

每个幸存者空间的大小与伊甸园空间大小的比率,其中<n>是比率。以下等式可用于确定使用-XX指定的比率的幸存者空间大小:SurvivorRatio = <n>:幸存者大小= -Xmn <n> /( - XX:SurvivorRatio = <n> + 2)其中-Xmn <n>是年轻代空间的大小,-XX:SurvivorRatio = <n>是指定为比率的值。等式中+ 2的原因是存在两个幸存者空间。指定为比率的值越大,幸存者空间大小越小。-XX:当你想要使用并发垃圾收集器显式调整幸存者空间大小来操纵对象老化时,应该使用SurvivorRatio = <n>

-XX:SurvivorRatio = <n>不应与启用了自适应大小调整的吞吐量收集器一起使用。默认情况下,通过-XX:+ UseParallelGC或-XX:+ UseParallelOldGC使用吞吐量垃圾收集器启用自适应大小调整。如果需要初始幸存者比率来开始吞吐量垃圾收集器的自适应大小调整,则应使用-XX:InitialSurvivorRatio = <n>。

使用Java创建内存泄漏


 

 

https://groups.google.com/a/jclarity.com/forum/#!search/jvm 

https://bugs.openjdk.java.net/projects/JDK/issues/JDK-8213225?filter=allopenissues

猜你喜欢

转载自blog.csdn.net/21aspnet/article/details/88772421