Java ParNew Collection将对象移动到Old Generation

时间:2013-12-01 17:06:51

标签: java object garbage-collection

那是我的VM论点:

-XX:MaxPermSize=128m 
-XX:+UseParNewGC 
-XX:MaxNewSize=1G 
-XX:NewSize=1G 
-Xms13G 
-Xmx13G 
-XX:SurvivorRatio=128 
-XX:MaxTenuringThreshold=0 
-XX:+UseTLAB 
-XX:+UseConcMarkSweepGC 
-verbose:gc 
-XX:+PrintGCDetails 
-XX:+PrintGCTimeStamps 
-Xloggc:./gc.log -cp

我还创建了内存泄漏:

{
    String s = "";
    for (int i = 0; i < objectsCount; i++)
        s += "s" + s;
}//Here all created objects should be garbage collected

所以我已经运行了几次这部分代码,我注意到大多数对象都被移到了Old Generation,只有一些是由小GC收集的

832.135: [GC 832.135: [ParNew: 1032095K->0K(1040512K), 0.7309045 secs] 4832264K->4761739K(13623424K), 0.7309703 secs] [Times: user=2.37 sys=0.33, real=0.73 secs] 
833.148: [GC 833.148: [ParNew: 826257K->0K(1040512K), 0.1510836 secs] 5587996K->5095138K(13623424K), 0.1511436 secs] [Times: user=0.33 sys=0.00, real=0.15 secs] 
833.567: [GC 833.567: [ParNew: 742459K->0K(1040512K), 0.2067575 secs] 5837597K->5836296K(13623424K), 0.2068291 secs] [Times: user=0.75 sys=0.00, real=0.21 secs] 
853.490: [GC 853.582: [ParNew: 993475K->0K(1040512K), 0.6963577 secs] 8100247K->7107608K(13623424K), 0.6968597 secs] [Times: user=1.61 sys=0.00, real=0.79 secs] 
879.973: [GC 879.973: [ParNew: 1032433K->0K(1040512K), 10.6403908 secs] 8140042K->8061725K(13623424K), 10.6404844 secs] [Times: user=30.93 sys=0.34, real=10.64 secs] 

我认为原因是,同时将太多的对象粘贴到内存中,因此垃圾收集器从Young Generation或Old Generation移动它们会更方便。

我的问题是,我的论点应该改变什么,让所有这些对象都被Small GC清除?

2 个答案:

答案 0 :(得分:0)

在循环中移动String s =“”然后尝试。

这里的事情是,在for循环完成之前,变量s没有标记为GC。您看到的GC日志条目是在for循环中进行的。因为程序耗尽了年轻的gen空间并且循环仍在运行,GC收集器将S的值移动到old gen,因为它不知道还能做什么。


而不是这样做

String s = "";
for(int i = 0; i < counter; i++){
    s = s + "something";
}

这样做

for(int i = 0; i < counter; i++){
    String s = "something";
    //call some methods to process it.
}

或使用StringBuilder创建字符串连接,而不是在字符串上使用+运算符。


-d64 -server -Xms4096m -Xmx4096m -XX:PermSize=512m -XX:MaxPermSize=512m -XX:NewSize=1536m -XX:MaxNewSize=1536m -XX:-UseAdaptiveSizePolicy -XX:+UseParNewGC -XX:+CMSParallelRemarkEnabled -XX:+UseTLAB -XX:+UseConcMarkSweepGC -XX:+OptimizeStringConcat -XX:ParallelGCThreads=14 -XX:ConcGCThreads=14

根据需要调整烫发尺寸。 NewSize是你的年轻人和休息堆剩余的东西留给老一代。尝试一下,看看它是否对你有帮助。

答案 1 :(得分:0)

让我为您解释一下您的JVM参数。

-XX:NewSize=1G - 这是年轻空间的大小(一个用“小”集合收集)。

-XX:SurvivorRatio=128 - 这会将年轻空间分成~1008 MiB的Enden + 2个幸存者空间,每个8 MiB。当伊甸园被填满时,年轻(“小”)收集就会发生。

-XX:MaxTenuringThreshold=0 - 此参数强制JVM立即将一个年轻GC幸存的对象提升到旧空间(因此永远不会使用幸存者空间)。通常,在升级到旧空间之前,对象应该存在几个“小”GC,但是您已明确禁用它。

Here您可以在HotSpot JVM中找到有关分代收集的更多详细信息。

Cheatsheet of HotSpot GC options也可能有用。