在Java堆中,空间/代之间的比率是否恒定?

13
我看过 这篇文章 关于虚拟机垃圾收集器调优,以更好地理解 Java 垃圾回收器。每个空间都有一个 虚拟 堆空间区域,当堆空间需要接近最大堆大小时,它可以扩展到该区域。这可以在此图片中看到: Java GC arrangement of generations
(来源: oracle.com) 您可以使用 NewRatio 参数设置 年轻代老年代(Tenured) 之间的比例,并使用 SurvivorRatio 参数设置 伊甸园空间幸存者空间 之间的比例。

最近有关于查找堆空间默认比率的问题this question。它说您应该使用PrintGCDetails参数并手动计算比率。

我的问题是:不同堆空间的大小是否按相同比例增加,从而在整个应用程序运行时保持它们之间的比率设置恒定?例如,如果年轻代和老年代/终身代有一个默认的NewRatio为3,并且年轻代的初始保留堆空间为100MB,老年代为300MB。如果需要为老年代保留更多的内存,假设需要再保留300MB使其总共达到600MB。那么为年轻代保留的内存也会加倍到200MB,保持比率不变吗?

3个回答

9
我认为你正在提到GC ErgonomicsAdaptive Size Policy
  • 这是Hotspot GC的一个功能,它可以根据运行应用程序的当前分配行为,在运行时自动调整代的大小
  • 此功能默认为启用状态,并可在运行时控制/调整各代的大小。
  • 实际上,如果您不禁用自适应大小策略,则将忽略一些GC参数,例如-XX: SurvivorRatio =

您可以使用 -XX:-UseAdaptiveSizePolicy 禁用AdaptiveSizePolicy。一旦禁用了AdaptiveSizePolicy,GC将尊重代的初始大小,这是由启动参数指定的(例如-Xms-Xmx-XX:MaxNewSize = -XX:NewSize = -XX:SurvivorRatio= ),并且它们将保持不变。

您可以在UseAdaptiveSizePolicy and other jvm opts中查找更多关于Adaptive Size策略的信息。


好的回答,解释了我之前不知道的一些概念。 - ghdalum

1

PermGen和Young generation的比例部分由JVM维护,但如果说这个比例被维护了,答案是

JVM7已经变得足够先进和复杂,我们不应该预测堆内分配的代数。

在JVM运行的每个GC周期中,它还会进行度量分析,以了解当前应用程序在内存存储方面的行为。 - 如果更多的对象在多个GC周期中幸存下来,则PermGen将减少,并且一些空间将分配给YoungGeneration。基本上,对象数量 x 它们跳过的GC周期数 在动态调整代数比例方面起着关键作用。

希望对您有所帮助,谢谢。


我不理解你回答的部分内容。“如果更多的对象在堆的多个周期中幸存下来,那么permgen会减少一些空间被分配给YoungGeneration。”如果更多的对象幸存下来,难道不应该是OldGeneration分配更多的内存吗?为什么要将permgen引入其中?如果在启动参数中指定了NewRatio,比例仍然不能保持吗? - ghdalum
1
这是一个好问题。 如果有更多的对象存活,难道不应该是OldGeneration分配更多的内存吗? 是的,应该是这样的。我的意思是“PermGen用于ClassLoaders,当JVM看到GC无法清除对象(由于有效原因),它会尝试从PermGen中检索未使用的内存并将其分配给对象存储。 关于您的问题,根据JVM使用的外推算法来确定近期分配,此分配将进入OldGeneration或新一代。 - Vishal Verma

1

编辑:我认为可能有一些错误。在调查时,我在此处放置了此注释,以避免将人们带入错误的道路!

如果您使用Parallel Scavenge GC(-XX:+UseParallelGC),那么Ales0x的答案非常好。但是,Concurrent Mark-Sweep GC(-XX:+UseConcMarkSweepGC)不支持自适应调整大小。

使用Concurrent Mark-Sweep时,新/年轻代大小基于初始堆大小设置(除非指定-XX:NewSize = )。随着堆增长,新生代的大小不会更改。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接