【问题标题】:Memory leak in Scala and processesScala 和进程中的内存泄漏
【发布时间】:2014-11-08 05:00:11
【问题描述】:

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

下图显示了一天的内存使用情况。当它达到极限时,进程关闭,我放了一个看门狗再次恢复它。

我会定期运行命令

jcmd <pid> GC.run

这使得内存增长缓慢,但泄漏仍然发生。

我使用 jvisualvm 进行分析,比较不同的时间点,增量为 40 分钟。下图显示了这两个时刻之间的比较。请注意,ConcurrentHashMap$HashEntrySNodeWeakReferencechar[]String 等某些类的实例以及 scala.collection.concurrent 包中的许多类的实例有所增加。

什么可能导致内存泄漏?

编辑 1: 调查 JVisualVM,我注意到 TriedMap 中的 CNode 和 INode 类的对象,它们在 sbt.TrapExit$App 类中实例化。这是对象层次结构图:

【问题讨论】:

  • 我看到 list.toStream.map,但是 scala.collection.concurrent 来自哪里?当您说“很多线程”时,您的意思是“foo.par”很多吗?我不是在问平行收藏方面的专家。您是否明确使用 TrieMap?
  • 很多线程我的意思是有数百个参与者,每个参与者都进行系统调用并创建一些未来来异步执行任务。我没有明确使用 TrieMap。
  • 你有更新的答案吗?我也有这个类似的问题。希望任何人都可以找出根本原因。提前致谢。

标签: java scala memory memory-leaks


【解决方案1】:

没有看到实现很难说。您帖子的标题表明 Scala 中存在内存泄漏,但您是否检查了您的实现是否存在释放对象的问题?

您是否检查了以下内容:

  • 你是否限制演员的数量?
  • 您是否为系统调用设置了超时时间?
  • 您是否允许在执行任务时从堆中删除参与者?
  • 您是否数过有多少演员可以放入您的记忆中,或者您只是在创建“数百个演员”,希望 jvm 知道“该做什么”

我想说的是,您可能内存不足,因为您只是创建了许多稍后不会释放的对象,因为它们仍在执行其任务(没有超时),或者您已经创建了许多他们。

也许您需要将您的应用程序扩展到多个 jvm?你用了多少个jvm?

【讨论】:

    【解决方案2】:

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

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

    接下来您需要分析堆转储以找出内存泄漏的来源。我推荐使用Eclipse MATLeak Suspects 报告应该让您了解哪些对象实际上导致了泄漏。

    【讨论】:

    • 通过堆差异,我已经知道泄漏的来源是什么。 ConcurrentHashMap$HashEntry 正在增加数字。但是我没有在我的代码中使用这些对象,所以它看起来像是 scala 或 jvm 中的东西
    • 您可能没有直接实例化对象,但它确实发生了。因此,您需要追溯创建这些对象的内容/时间/地点。那么谁创建了 CNode 实例等。某些对象保留对 CNode 的引用,以防止它(及其引用的对象)被垃圾收集。 Eclipse MAT 有这个视图 - help.eclipse.org/luna/… 应该会给你一些信息。
    猜你喜欢
    • 1970-01-01
    • 2018-11-12
    • 2019-02-17
    • 2017-12-21
    • 2012-09-12
    • 2015-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多