在运行MetaMap(带有Java API和UIMA包装器)时,我们总是遇到java.lang.OutOfMemoryError: Java heap space
错误。
不幸的是,这些日志信息不多,因此我们不知道它要压缩的文件。
过去,我们遇到过MetaMap在遇到管道(|
)符号时创建巨大的圆形注释的问题。但是,我们正在使用的文件集(MIMIC notes)不包含任何管道符号。还有其他字符可能表现出与管道符号类似的行为吗?
我们可以增加系统RAM来避免堆空间问题(由于系统RAM受限制,实际上无法使用最大设置的堆,其设置为6 GB),但是我们希望知道是什么原因导致了问题,尤其是自那时以来,输出文件的大小更易于管理。
*编辑*
仅需澄清一下:我们增加了JVM的内存资源,这确实有助于实际推送数据(这已在本地VM上进行了测试)。 MetaMap的问题在于,它会创建大量的循环注释,这些注释会耗尽JVM资源(在我们当前的系统上,OS RAM并不是最佳的)。
正如我在下面的评论中所指出的,我们对文件进行预处理,以去除所有引发错误的字符。不过,堆空间错误有点令人讨厌,因为与我们遇到的其他错误(例如,在text . text
中围绕一个单独的句点的空格)不同,这些错误只会引发解析错误,并带有引发错误的文本。对于管道符号,我们通过增加RAM(在我们最初对其进行测试的VM上)然后在UIMA查看器中查看注释来找到它。由于带有圆形注释的XMI的输出文件很大,因此我们能够识别出有问题的文件。
我们将再次在VM上运行一些测试,以查看是否可以确定问题,但是如果有人具有MetaMap经验来帮助我们确定任何问题字符或字符序列,那将是可取的。
*编辑2 *
内存应该不是问题。我们正在使用export JAVA_TOOL_OPTIONS='-Xms2G -Xmx6G -XX:MinHeapFreeRatio=25 -XX:+UseG1GC'
我们正在尝试解决的圆形注释存在一个基本问题。这吞噬了资源并呕吐。
答案 0 :(得分:1)
您的Java应用很可能会使用到限制分配的堆空间,并达到垃圾回收器无法有效获取必要堆空间的地步。
考虑到您的应用程序正在有效地使用分配的堆空间,我认为您唯一的选择是增加分配的堆空间。您可以进行此总线
java -Xmx2048m -jar YourApp.jar
但是,也许值得分析一下堆空间的使用方式。有一些工具可以帮助您做到这一点。如果使用IntelliJ,则可以尝试使用VisualVM插件。
答案 1 :(得分:0)
我想添加来自oracle trouble shooting article的推荐
线程thread_name中的异常: java.lang.OutOfMemoryError:Java堆空间
详细消息Java堆空间指示对象不能 在Java堆中分配。此错误并不一定意味着 内存泄漏
可能的原因:
简单的配置问题,其中指定的堆大小
不足以用于该应用程序。
此错误的另一个潜在来源是应用程序 过多使用终结器。如果某个类具有finalize方法, 那么该类型的对象就不会在垃圾回收中回收它们的空间 收集时间
垃圾回收之后,对象将排队等待定稿,这将在以后发生。终结器由为终结队列提供服务的守护程序线程执行。如果终结器线程无法跟上终结器队列的速度,则Java堆可能会填满,并且会抛出这种类型的 OutOfMemoryError
异常。
可能导致这种情况的一种情况是,应用程序创建了高优先级线程,这些线程导致终结处理队列以比终结器线程为该队列提供服务的速率快的速率增加。
答案 2 :(得分:0)
解决方案有两个方面:
有一个UIMA JVM环境变量需要设置为export UIMA_JVM_OPTS="-Xms128M -Xmx5g"
其次,有一个MetaMap开关可以减少用于创建注释的递归深度(位于MetaMapApiAE.xml配置文件中):
<configurationParameterSettings>
... previous settings omitted ...
<nameValuePair>
<name>metamap_options</name>
<value>
<string>--prune 30</string>
</value>
</nameValuePair>
</configurationParameterSettings>