当前位置: 首页 > 知识库问答 >
问题:

尽管NewRatio=2,但年轻一代还是很小

秦炜
2023-03-14

在某个时刻,我的应用程序开始创建许多临时阵列,这是预期的行为,我想给年轻一代提供大量空间,所以临时阵列不会被提升到终身一代。

JVM选项:java-Xmx240g-XX:useConMarkSweepGC-XX:NewRatio=2-XX:PrintGCTimeStamps-verbose:gc-XX:PrintGCDetails

在某些时候,我的GC日志开始看起来像这样:

800.020: [GC 800.020: [ParNew: 559514K->257K(629120K), 0.1486790 secs] 95407039K->94847783K(158690816K), 0.1487540 secs] [Times: user=3.34 sys=0.05, real=0.15 secs] 
800.202: [GC 800.202: [ParNew: 559489K->246K(629120K), 0.1665870 secs] 95407015K->94847777K(158690816K), 0.1666610 secs] [Times: user=3.79 sys=0.00, real=0.17 secs] 
800.402: [GC 800.402: [ParNew: 559478K->257K(629120K), 0.1536610 secs] 95407009K->94847788K(158690816K), 0.1537290 secs] [Times: user=3.48 sys=0.02, real=0.15 secs]

我非常困惑的事实,年轻一代的大小是629120K(=629M),而我预计它是约1/2(因为NewRatio=2)的终身一代大小这是158690816K(=158G)。终身大小生成对应于NewRatio和Xms的预期,即它是总堆大小的2/3。

JVM版本:java版本“1.7.0_21”java(TM)SE运行时环境(构建1.7.0_21-b11)java热点(TM)64位服务器虚拟机(构建23.21-b01,混合模式)

更新: <罢工> 我相信在这一点上(800 sec的运行时间)程序有峰值临时数组的使用。如果程序没有超出629M年轻一代的大小,这是否意味着我应该增加NewRatio?让我们假设我打算给程序更多的工作负载,我预计临时数组卷与永久数组卷的比例将是相同的。

我之前使用NewRatio=8运行程序,gc log主要由以下行组成:

800.004: [GC 800.004: [ParNew: 186594K->242K(209664K), 0.1059450 secs] 95345881K->95159529K(126655428K), 0.1060110 secs] [Times: user=2.41 sys=0.00, real=0.10 secs] 
800.122: [GC 800.122: [ParNew: 186610K->221K(209664K), 0.1073210 secs] 95345897K->95159522K(126655428K), 0.1073900 secs] [Times: user=2.37 sys=0.07, real=0.11 secs] 
800.240: [GC 800.240: [ParNew: 186589K->221K(209664K), 0.1026210 secs] 95345890K->95159524K(126655428K), 0.1026870 secs] [Times: user=2.34 sys=0.00, real=0.10 secs] 
800.357: [GC 800.357: [ParNew: 186589K->218K(209664K), 0.1043130 secs] 95345892K->95159527K(126655428K), 0.1043810 secs] [Times: user=2.30 sys=0.07, real=0.10 secs] 

这让我觉得NewRatio对当前年轻一代的大小有影响,但不应该,因为当前年轻一代的大小远低于堆大小的1/9。

更新2:这是一个巨大的科学计算,我的解决方案需要高达240GB的内存。这不是内存泄漏,算法是我能想到的最好的。

共有2个答案

薛博赡
2023-03-14

首先,检查-XX: NewRatio和-XX: OldSize JVM标志的含义是什么?

NewRatio是年轻一代与老一代的比率(例如,值2意味着老一代的最大大小将是年轻一代最大大小的两倍,即年轻一代可以获得堆的1/3)。

你们会发现你们年轻一代的规模是正确的。

我建议您检查Java堆中的空间/代之间的比率是否为常数?并从一开始就使用

-Xms240g -Xmx240g -XX:NewSize=120g -XX:MaxNewSize=120g -XX:-UseAdaptiveSizePolicy
武成和
2023-03-14

请尝试在禁用AdaptiveSizePolicy的情况下运行,使用:-XX UseAptiveSizePolicy

这将允许您预设每个堆区域的大小,并将在运行时禁用对其大小的动态更改。

 类似资料:
  • 我们使用G1收集器<当一个年轻的GC发生时(不是混合GC),堆的变化:[Eden:3666.0M(3666.0M)- 堆的变化为4819.1M(5346.0-526.9) 伊甸园改变了3666.0(3666.0-0.0)和幸存者-34M(20-54);为什么堆的变化不等于伊甸园和幸存者的总和(4819.1不等于(3666.0-34))?年轻的GC清除对象在老一代? gc日志:

  • 问题内容: 是否将“静态最终”直接分配给年轻一代或老一代或烫发一代?(我猜想在我认为的时间内,它很可能会降落到旧的gen中。)如果在perm gen中分配了它,那么当在Perm Gen中进行类卸载时,是否会收集垃圾? 问题答案: 是否将“静态最终”直接分配给年轻一代或老一代或烫发一代? 变量引用的对象将根据与其他任何对象相同的规则进行分配。它最有可能在年轻一代或老一代中分配(如果它很大,并且适用某

  • 问题内容: 我对Heap,Young,Tenured和Perm一代感到困惑。 谁能解释一下? 问题答案: Java垃圾收集器被称为分 代垃圾收集器 。应用程序中的对象生存的时间长短不一,具体取决于它们的创建位置和使用方式。此处的主要见解在于,针对短期和长期对象使用不同的垃圾回收策略,可以针对每种情况专门优化GC。 松散地说,当对象在新 世代中 “生存”重复的垃圾回收时,它们将迁移到 终身代 。该

  • 我在尝试理解垃圾收集机制,我在研究代际算法,我有一个关于年轻人和老年人的代沟的问题。我读到,在年轻一代开始收集物品,GC是从GC根开始标记它们,以找到活的,通常它会将它们复制到幸存者空间,清除年轻一代区域,然后瞧。 我不明白,如果我们从GC根开始,我们开始遍历活动对象,我们不是也在旧一代中找到了对象吗?这是否意味着,当我们击中旧空间中的一个物体时,我们会在那个点上停止跟踪参照物?

  • 如果我错了,请随时指正。在JVM堆中,有老一代和年轻一代两代。在做全GC时,在老一代中,有像紧凑空间和修复漏洞这样的繁重操作,这会使JVM挂起。而我发现在年轻一代中,应用了一个轻量级的GC,从我的搜索结果中还有一个叫做Eden的区域涉及年轻一代。但是,在搜索了很多文档后,我对年轻一代中的GC仍然有两个困惑, 在年轻一代中,GC似乎不像老一代GC那样工作(即老一代GC压缩并修复漏洞)?如果是这样,年

  • 我正在为max分配8GB内存给Java编写的应用程序。它会内存溢出。我相信年轻一代总是比默认情况下的老一代小(堆的1/4)。而Eden/幸存者1,2在年轻一代内部。我相信在Eden空间中创建了新对象。 即使老一代还没有满,但年轻一代已经完全满了,java应用程序还是会耗尽内存吗? 如果短寿命的对象比长寿命的对象多,那么可以为年轻一代分配更多内存,或者至少将堆的50%分配给年轻一代吗?或者,由于jv