那是我的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清除?
答案 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中找到有关分代收集的更多详细信息。