我正在尝试调整GC,使其在短基准测试期间不会启动。
为此,我试图让年轻一代尽可能地大,并确保我创造的垃圾少于伊甸园的大小。
我使用了以下参数:
java -Xmx1g -Xms1g -Xmn1g -XX:NewSize=1000m -XX:MaxNewSize=1g -XX:SurvivorRatio=10000 -verbose:gc Main
但由于某些原因,当VM内存仅为300M时,我仍然会看到[Full GC]日志,是否有任何JVM调整我缺少?
答案 0 :(得分:2)
你的幸存者配给非常重要,有10 000你告诉JVM幸存者空间是伊甸园大小的10000倍。
如果幸存者空间太小,则复制集合会直接溢出到终身代。如果幸存者空间太大,它们将毫无用处。在每次垃圾收集时,虚拟机选择一个阈值次数,可以在对象被终止之前复制该对象。选择此阈值是为了使幸存者保持半满。命令行选项-XX:+ PrintTenuringDistribution可用于显示此阈值和新一代中对象的年龄。它对于观察应用程序的生命周期分布也很有用。
因此,幸存者空间比率如此之低,您的对象将直接存储在终身属性中。
当终身代已满时,会发生主要收藏,这就是您在日志中看到[Full GC...]
的原因。
如果你想让年轻一代更大的使用:
-XX:NewRatio=1
这意味着伊甸园和幸存者空间的总大小将是总堆大小的一半。 (我猜你不可能有更大的年轻一代)
如果您已设置-XX:NewSize
,则{1>}也不必设置-Xmn
,-Xmn
与1.4相同。而且我猜你不想用-XX:MaxNewSize
绑定上面的年轻人,默认值是无限制的。但是将年轻代的大小设置为与最大堆大小相同的值意味着你不要为老一代留出空间,所以我猜JVM会重新调整代数。
总之,还有一些情况,分配可以直接发生在终身代。 (Do objects ever get allocated directly into the old generation?)
- 如果在年轻代中分配失败并且对象是不包含对对象的任何引用的大型数组,则可以将其直接分配给旧代。在一些选择的实例中,该策略旨在通过从旧一代分配来避免年轻一代的收集。 阈值大小为64k字。
答案 1 :(得分:2)
您可以获得完整的GC,因为您的终身空间已经填满(大型物体直接放入终身空间)
我通常尝试4到24 GB的伊甸园大小,但确保终身空间大小为0.5到2 GB。
答案 2 :(得分:1)
如果要释放大量的对象,GC仍然会运行,这不仅仅是等到你已经使用了所有已分配的空间,如果这样做会导致严重的GC抖动。它确实运行了。
您应该关注对象处理的使用以及是否可以提高效率。通过更新对象值,查看LMAX中断模式,了解如何使用对象进行重用,而不是取消分配替换对象本身。
话虽如此,这篇关于调整GC的文章非常好 - http://developer.amd.com/documentation/articles/pages/4EasyWaystodoJavaGarbageCollectionTuning.aspx