PNS*_*PNS 317 java heap heap-memory hashmap g1gc
我在一个程序中得到这个错误,该程序创建了几个(几十万个)HashMap对象,每个对象有几个(15-20)个文本条目.在提交到数据库之前,必须收集这些字符串(不会分解成较小的数量).
根据Sun的说法,如果在垃圾收集中花费了太多时间,则会发生错误:如果超过98%的总时间花在垃圾收集上,并且不到2%的堆被恢复,则会抛出OutOfMemoryError. ".
显然,可以使用命令行将参数传递给JVM
第一种方法工作正常,第二种方法在另一个java.lang.OutOfMemoryError中结束,这次是关于堆的.
所以,问题:对于特定的用例(即几个小的HashMap对象),是否有任何编程替代方案?例如,如果我使用HashMap clear()方法,问题就会消失,但HashMap中存储的数据也会消失!:-)
StackOverflow中的相关主题也讨论了该问题.
Whi*_*g34 157
你基本上没有内存来顺利运行这个过程.想到的选项:
-Xmx512m
第一个之间尝试一下HashMap
如果可能,使用较小批次的对象进行处理String.intern()
在将它们放入之前使用它们HashMap
HashMap(int initialCapacity, float loadFactor)
构造函数来调整您的案例Min*_*wzy 60
以下对我有用.只需添加以下代码段:
dexOptions {
javaMaxHeapSize "4g"
}
Run Code Online (Sandbox Code Playgroud)
给你的build.gradle
:
android {
compileSdkVersion 23
buildToolsVersion '23.0.1'
defaultConfig {
applicationId "yourpackage"
minSdkVersion 14
targetSdkVersion 23
versionCode 1
versionName "1.0"
multiDexEnabled true
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
packagingOptions {
}
dexOptions {
javaMaxHeapSize "4g"
}
}
Run Code Online (Sandbox Code Playgroud)
qup*_*era 42
@takrl:此选项的默认设置为:
java -XX:+UseConcMarkSweepGC
Run Code Online (Sandbox Code Playgroud)
这意味着,默认情况下此选项不活动.所以,当你说你使用选项" +XX:UseConcMarkSweepGC
"时,我假设你使用的是这种语法:
java -XX:+UseConcMarkSweepGC
Run Code Online (Sandbox Code Playgroud)
这意味着您明确激活了此选项.有关Java HotSpot VM Options
@本
文档的正确语法和默认设置
tak*_*krl 23
为了记录,我们今天遇到了同样的问题.我们使用此选项修复它:
-XX:-UseConcMarkSweepGC
Run Code Online (Sandbox Code Playgroud)
显然,这修改了用于垃圾收集的策略,这使得问题消失了.
cor*_*ttk 12
嗯......你要么:
完全重新考虑您的算法和数据结构,这样它就不需要所有这些小HashMaps.
创建一个外观,允许您根据需要在内存中分页这些HashMaps.简单的LRU缓存可能就是故障单.
增加JVM可用的内存.如果你有管理这台野兽的机器,即使购买更多的RAM也可能是最快,最便宜的解决方案.话虽如此:我通常不是"投入更多硬件"解决方案的粉丝,特别是如果可以在合理的时间范围内考虑替代算法解决方案.如果你继续在每一个问题上投入更多的硬件,你很快就会遇到收益递减规律.
无论如何你还想做什么?我怀疑你的实际问题有更好的方法.
在等待结束时,不要将整个结构存储在内存中.
写中间结果到一个临时表在数据库中,而不是包含HashMap - 功能,数据库表是一个HashMap的相同,即都支持键控访问数据,但该表不是内存约束,所以这里使用索引表,而不是哈希图.
如果正确完成,你的算法甚至不应该注意到这种变化 - 这里正确的意思是使用一个类来表示表,甚至给它一个put(键,值)和一个get(key)方法就像一个hashmap.
中间表完成后,从中生成所需的sql语句而不是从内存中生成.
小智 8
OutOfMemoryError
如果在垃圾收集中花费了太多时间,并行收集器将抛出.特别是,如果超过总时间的98%用于垃圾收集并且不到2%的堆被恢复,OutOfMemoryError
则将被抛出.此功能旨在防止应用程序长时间运行,同时由于堆太小而很少或没有进度.如有必要,可以通过向-XX:-UseGCOverheadLimit
命令行添加选项来禁用此功能.
如果您正在创建数十万个哈希映射,那么您可能使用的远远超过实际需要; 除非您使用大型文件或图形,否则存储简单数据不应超出Java内存限制.
您应该尝试重新考虑您的算法.在这种情况下,我会就该主题提供更多帮助,但在您提供有关问题背景的更多信息之前,我无法提供任何信息.
如果您有java8,并且可以使用G1垃圾收集器,那么运行您的应用程序:
-XX:+UseG1GC -XX:+UseStringDeduplication
Run Code Online (Sandbox Code Playgroud)
这告诉G1找到类似的字符串,并且只保留其中一个字符串,其他字符串只是内存中指向该字符串的指针.
当你有很多重复的字符串时,这很有用.该解决方案可能有效或无效,取决于每个应用程序.
更多信息:
https
://blog.codecentric.de/en/2014/08/string-deduplication-new-feature-java-8-update-20-2/ http://java-performance.info/java-串的重复数据删除/
归档时间: |
|
查看次数: |
593161 次 |
最近记录: |