我在一个程序中得到这个错误,该程序创建了几个(几十万个)HashMap对象,每个对象有几个(15-20)个文本条目.在提交到数据库之前,必须收集这些字符串(不会分解成较小的数量).
根据Sun的说法,如果在垃圾收集中花费了太多时间,则会发生错误:如果超过98%的总时间花在垃圾收集上,并且不到2%的堆被恢复,则会抛出OutOfMemoryError. ".
显然,可以使用命令行将参数传递给JVM
第一种方法工作正常,第二种方法在另一个java.lang.OutOfMemoryError中结束,这次是关于堆的.
所以,问题:对于特定的用例(即几个小的HashMap对象),是否有任何编程替代方案?例如,如果我使用HashMap clear()方法,问题就会消失,但HashMap中存储的数据也会消失!:-)
StackOverflow中的相关主题也讨论了该问题.
我有以下情况:有几台机器组成一个集群.客户端可以加载数据集,我们需要选择将加载数据集的节点,如果没有一台机器可以适合数据集,则拒绝加载/避免OOM错误.
我们当前所做的事情:我们现在entry count在数据集中估算memory to be usedas entry count * empirical factor(手动确定).然后检查它是否低于空闲内存(得到Runtime.freeMemory()),如果是,则加载它(否则重做其他节点上的进程/报告没有空闲容量).
这种方法的问题是:
empirical factor需要被重新和手动更新freeMemory有时可能会因为一些未清理的垃圾而少报(这可以通过System.gc在每次这样的通话之前运行来避免,但这会减慢服务器的速度并且还可能导致过早的促销)这个问题有更好的解决方案吗?
我注意到在java中播放音频时,gc中的MarkSweepCompact阶段太长并导致短暂的静音,这是不可接受的.所以我需要使用低暂停gc.我尝试过Parallel和CMS,它们似乎工作得更好,因为我认为暂停时间更短,并且它们不会像默认那样经常完全收集.
到目前为止,我已经使用ParallelGC的以下选项测试了我的程序:
-XX:+UseParallelGC
-XX:MaxGCPauseMillis=70
Run Code Online (Sandbox Code Playgroud)
对于ConcurrentMarkSweep:
-XX:+UseConcMarkSweepGC
-XX:+CMSIncrementalMode
-XX:+CMSIncrementalPacing
Run Code Online (Sandbox Code Playgroud)
我也尝试过G1GC,但它仍然在java 6中实验性.两种模式的选项:
-Xms15m
-Xmx40m
-XX:+UnlockExperimentalVMOptions
-XX:+CMSClassUnloadingEnabled
-XX:+TieredCompilation
-XX:+AggressiveOpts
-XX:+UseAdaptiveSizePolicy
-Dsun.java2d.noddraw=false
-Dswing.aatext=true
-XX:MaxPermSize=25m
-XX:MaxHeapFreeRatio=10
-XX:MinHeapFreeRatio=10
Run Code Online (Sandbox Code Playgroud)
哪种GC在这种情况下更好?是否可以针对最佳CPU性能和最小内存使用量对这些设置进行优化?
编辑为了识别暂停,我记录了将音频数据写入输出线的时间,通常在92到120毫秒之间(我写的是16384字节= ~92毫秒),广告在运行全GC时,它是200+毫秒:
65.424: [Full GC (System) [PSYoungGen: 872K->0K(2432K)] [PSOldGen: 12475K->12905K(16960K)] 13348K->12905K(19392K) [PSPermGen: 15051K->15051K(22272K)], 0.2145081 secs] [Times: user=0.20 sys=0.00, real=0.21 secs]
Was writing 16384 bytes, time to write 263 ms
Run Code Online (Sandbox Code Playgroud)
EDIT2我的应用程序的分配模式如下:它在启动时加载一堆对象,然后它开始播放,我猜之后的大多数对象都由gui分配,因为凝视/暂停音频不会改变GC图形许多.这是visualgc与并行gc一起显示的内容:

图表在启动时开始,我开始播放.标记是
1)声音延迟和完整的gc,我认为它增加了旧尺寸:
101.646: [Full GC [PSYoungGen: 64K->0K(6848K)] [PSOldGen: 15792K->12773K(19328K)] 15856K->12773K(26176K) [PSPermGen: 15042K->14898K(23808K)], 0.2411479 secs] [Times: user=0.19 sys=0.00, real=0.24 secs]
Run Code Online (Sandbox Code Playgroud)
2)我打开应用程序窗口并暂停播放.什么都没有改变,稍后它增加了伊甸园的大小.
3)我打开窗口再次开始播放.
所以我需要增加分配的旧Gen大小?我怎么做?我正在使用-XX:NewRatio = 10和-XX:NewSize = …
我有一个导致创建大量垃圾的应用程序.第一个(和几乎一个)标准是低GC暂停时间.我使用visualgc工具(和gc日志)尝试不同的GC参数.最佳参数如下.
-XX:+ UseConcMarkSweepGC
-Xmx1172M
-Xms600M
-XX:+ UseParNewGC
-XX:新尺寸= 150M
我的应用程序在带有Java 1.6.0_21的SunOS 10上运行.硬件是2 x CPU四核(uname -X结果是numCPU = 8).
问题是
观察GC行为,在伊甸园空间上创建新对象,直到伊甸园已满.当eden space full GC运行时,清除垃圾,如果对象不是死复制到Old-gen(我丢弃'从'&'到'空格),同样Old-Gen已满,GC运行与CMS并发阶段并清除旧-gen空间.CMS的某些部分是Stop-the-world(暂停时间).这是一个循环.
谢谢