Scala中的内存泄漏和进程问题

14

我在Scala中有一个系统,有很多同时运行的线程和系统调用。这个系统存在一些问题,因为内存使用量随着时间的推移而增加。

下面的图片显示了一天内的内存使用情况。当达到限制时,进程会关闭,然后我会放置一个看门狗来恢复它。 inserir a descrição da imagem aqui

我定期运行以下命令

jcmd <pid> GC.run

这导致内存逐渐增加,但仍然存在泄漏。

我使用jvisualvm进行了分析,对比了两个时间点,时间间隔为40分钟。下面的图片显示了这两个时间点之间的比较。请注意,一些类的实例数量增加了,例如ConcurrentHashMap $ HashEntrySNodeWeakReferencechar []String ,以及scala.collection.concurrent包中的许多类。

memory leaked ojects

是什么导致了内存泄漏?

编辑1: 通过调查JVisualVM,我发现了TriedMap中实例化的CNode和INode类的对象,该类是在sbt.TrapExit $ App类中实例化的。以下是对象层次结构图:

object hierarchy


1
https://dev59.com/7EjSa4cB1Zd3GeqPHrWB?rq=1 http://stackoverflow.com/questions/7944148/weakreference-and-memory-leaks https://dev59.com/POo6XIcBkEYKwwoYTS5D - Tony
我看到了list.toStream.map,但是scala.collection.concurrent从哪里来的?当你说“很多线程”时,你是指你经常使用“foo.par”吗?我不是作为并行集合方面的专家在问。你是否明确地使用了TrieMap? - som-snytt
有很多线程,我的意思是有数百个执行者,每个执行者都会进行系统调用并创建一些未来对象以异步执行任务。我没有明确使用TrieMap。 - Daniel Cukier
你有更新的答案吗?我也遇到了类似的问题。希望有人能找出根本原因。提前感谢。 - Haimei
2个回答

3

当您的应用程序因内存不足而崩溃时,请首先捕获堆转储。在启动JVM时添加以下标志:

-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/path/to/dump

接下来你需要分析堆转储以找出内存泄漏的源头。我建议使用Eclipse MATLeak Suspects 报告应该能给你一个对象实际上是导致内存泄漏的感觉。


通过堆差异,我已经知道了泄漏的源头。ConcurrentHashMap$HashEntry数量在增加。但是我在我的代码中没有使用这些对象,所以看起来像是scala或jvm内部的问题。 - Daniel Cukier
你可能没有直接实例化对象,但它确实发生了。因此,您需要追溯到这些对象是在什么时候、何地创建的。那么是谁创建了CNode实例等。某个对象保留了对CNode的引用,防止它(以及它引用的对象)被垃圾回收。Eclipse MAT有这个视图 - http://help.eclipse.org/luna/index.jsp?topic=%2Forg.eclipse.mat.ui.help%2Ftasks%2Ffindingresponsibleobjects.html ,应该会给您一些信息。 - rrevo

0

没有看到实现细节,很难下结论。你的帖子标题表明Scala存在内存泄漏问题,但你是否检查过在释放对象方面是否存在问题?

你是否进行了以下检查:

  • 你是否限制了actor的数量?
  • 你是否为系统调用设置了超时?
  • 当actor完成任务后,你是否允许将其从堆中删除?
  • 你是否统计过内存中可容纳多少actor,或者仅仅是创建了“数百个actor”,希望jvm知道“该怎么做”?

我的意思是,也许你会因为简单地创建了太多后续未被释放的对象而耗尽内存,因为它们要么还在执行任务(无超时),要么你已经创建了太多。

也许你需要将应用程序扩展到多个jvm上?你使用多少个jvm?


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接