我在一个程序中得到这个错误,该程序创建了几个(数十万)HashMap对象,每个对象有几个(15-20)文本条目。在将这些字符串提交到数据库之前,必须收集所有这些字符串(而不将其分解为更小的数量)。

根据Sun的说法,错误发生在“如果在垃圾收集上花费了太多的时间:如果超过98%的总时间花在垃圾收集上,而不到2%的堆被恢复,则会抛出OutOfMemoryError”。

显然,可以使用命令行将参数传递给JVM

增加堆的大小,通过“-Xmx1024m”(或更多),或者 通过"-XX:-UseGCOverheadLimit"完全禁用错误检查。

第一种方法工作得很好,第二种方法在另一个java.lang中结束。OutOfMemoryError,这次是关于堆的。

那么,问题是:对于特定的用例(即几个小HashMap对象),是否有任何编程替代方案?例如,如果我使用HashMap clear()方法,问题就会消失,但存储在HashMap中的数据也会消失!: -)

该问题也在StackOverflow的相关主题中进行了讨论。


当前回答

不要在等待结束时将整个结构存储在内存中。

将中间结果写入数据库中的临时表,而不是hashmap——从功能上讲,数据库表相当于hashmap,即两者都支持按键访问数据,但表不受内存限制,因此在这里使用索引表而不是hashmap。

如果操作正确,您的算法甚至不应该注意到这个变化——这里的正确意思是使用一个类来表示表,甚至像hashmap一样给它一个put(键,值)和get(键)方法。

当中间表完成时,从中间表而不是从内存中生成所需的sql语句。

其他回答

如果出现错误:

"内部编译器错误:java.lang.OutOfMemoryError: GC开销限制超过java.lang.AbstractStringBuilder"

将java堆空间增加到2GB,即-Xmx2g。

这帮助我摆脱了这个错误。此选项将禁用 - xx: + DisableExplicitGC

你需要在Jdeveloper中增加内存大小,转到setDomainEnv.cmd。

set WLS_HOME=%WL_HOME%\server
set XMS_SUN_64BIT=256
set XMS_SUN_32BIT=256
set XMX_SUN_64BIT=3072
set XMX_SUN_32BIT=3072
set XMS_JROCKIT_64BIT=256
set XMS_JROCKIT_32BIT=256
set XMX_JROCKIT_64BIT=1024
set XMX_JROCKIT_32BIT=1024

if "%JAVA_VENDOR%"=="Sun" (
    set WLS_MEM_ARGS_64BIT=-Xms256m -Xmx512m
    set WLS_MEM_ARGS_32BIT=-Xms256m -Xmx512m
) else (
    set WLS_MEM_ARGS_64BIT=-Xms512m -Xmx512m
    set WLS_MEM_ARGS_32BIT=-Xms512m -Xmx512m
)
and

set MEM_PERM_SIZE_64BIT=-XX:PermSize=256m
set MEM_PERM_SIZE_32BIT=-XX:PermSize=256m

if "%JAVA_USE_64BIT%"=="true" (
    set MEM_PERM_SIZE=%MEM_PERM_SIZE_64BIT%

) else (
    set MEM_PERM_SIZE=%MEM_PERM_SIZE_32BIT%
)

set MEM_MAX_PERM_SIZE_64BIT=-XX:MaxPermSize=1024m
set MEM_MAX_PERM_SIZE_32BIT=-XX:MaxPermSize=1024m

@takrl:默认设置为:

java -XX:+UseConcMarkSweepGC

这意味着,默认情况下,该选项不是活动的。所以当你说你使用了期权 “+ XX: UseConcMarkSweepGC” 我假设你使用的是这样的语法:

java -XX:+UseConcMarkSweepGC

也就是说你明确地激活了这个选项。 为正确的语法和Java热点虚拟机选项的默认设置@此 文档

使用替代HashMap实现(Trove)。标准Java HashMap有12倍的内存开销。 你可以在这里阅读细节。