我有多个线程运行自然语言处理应用程序。
偶尔我的一个线程因OutOfMemoryException而死亡。
我已经以合理的信心确诊了这个问题。根据解释here,垃圾收集占用了所有的cpu时间。
根据我的日志:
[INFO] 2016-07-30 13:43:53,442:
总记忆:7165968384(6834.0 MiB)
最大记忆:7635730432(7282.0 MiB)
免费记忆:2296592136(2190.2009353637695 MiB)
FileioThread currentFile currentFileProcessTime:4392
文本分析线程currentFile currentFileProcessTime:244443
PersistenceThread currentFile currentFileProcessTime:1588
[INFO] 2016-07-30 13:43:53,442:ikoda.jobanalysis.JobAnalysisThread.run(JobAnalysisThread.java:400)JobAnalysisThread run to to sleep for 30000 millis。
[INFO] 2016-07-30 13:45:40,717: 总内存:6028787712(5749.5 MiB)
最大记忆:7635730432(7282.0 MiB)
免费记忆:5045040128(4811.3251953125 MiB)
fileioThread currentFile currentFileProcessTime:73502
Ta Thread currentFile currentFileProcessTime:351718
persistenceThread currentFile currentFileProcessTime:38
主要观察结果: JVM中似乎有足够的内存。 文本分析线程花了超过5分钟分析一个文件(表明文件很长或文件中有一些很长的句子)。很可能垃圾收集正在超时运行,在文本文件的每个段落的每个句子中清除每个单词的多个令牌。
当前行为 随机线程会爆炸并因outOfmemoryException而死亡。 (不一定是TextAnalysis线程)。监视器线程确保死线确实已死,暂停30秒然后创建一个新实例。
一切都继续变得笨拙。
第三方已知问题 这里一个重要的注意事项是文本分析线程使用第三方Stanford NLP包。这些包确实创建了很多对象(每个单词nx个对象),所以gc有时会极端,但会恢复。
问题 创建替换线程实例看起来是良性的。此外,该程序收集大数据,线程重新生成期间的数据丢失是轻微和无害的。将程序放在速度更快的服务器上永远不会完全解决问题。然而,假装OutOfMemoryErrors并没有违背我的直觉和训练。 有人可以提出一些处理这个问题的策略。