【问题标题】:Clojure eval causes garbage collector to hangClojure eval 导致垃圾收集器挂起
【发布时间】:2016-09-16 21:00:17
【问题描述】:

我在运行使用 eval 的遗传编程算法时遇到了这个问题。

为了说明问题,我将其缩小到以下代码片段:

(loop []
  (do 
    (eval (list '+ (rand) (rand)))
    (recur)))

当我运行代码时,垃圾收集器会从元空间卸载所有创建的 $eval_n 类,但在第二次垃圾收集器调用时它会挂起。

我将 jdk1.8.0_102 与以下 JVM 选项一起使用: -XX:元空间大小=200m -XX:MaxMetaspaceSize=200m

一段时间后,我收到以下错误:

CompilerException java.lang.OutOfMemoryError: Metaspace, compiling:(form-init2581690491924993906.clj:1:1) 

编辑: 我添加了一个 visualVM 的屏幕截图来显示行为,当 JVM 挂起时,图表不再更新,它继续使用完整的 CPU 内核。

我也尝试过使用 java 7(没有任何 JMV 选项),但我在使用 PermGen 时遇到了同样的问题。

有什么办法可以避免这个问题吗?

编辑:

仅当我从 leinigen-REPL 使用 eclipse-逆时针运行它时才会出现此问题。如果我从基本命令行 REPL 运行代码,则不会出现问题!

【问题讨论】:

  • 只是想知道,你怎么知道“[它在第二次垃圾收集器调用时挂起”?以及如何运行此代码来获取错误?我无法重现它。你能提供确切的命令吗?
  • @ErwinRooijakkers,我添加了 VisualVM 图表的屏幕截图。
  • 谢谢。我安装了这个程序,并在 Java 1.7.0_80 的 REPL 中使用 Cider 从 Emacs 运行你的循环。它运行良好,垃圾收集周期是一致的。见i.imgur.com/wHYEmII.png
  • @ErwinRooijakkers 感谢您的努力。我想知道为什么你的图表没有显示加载类的数量有任何差异。
  • 以什么方式运行代码?

标签: clojure garbage-collection eval metaspace


【解决方案1】:

我注意到上述示例的内存消耗在稳步增加。添加系统/gc

(loop [] (do (eval (list '+ (rand) (rand))) (System/gc)) (recur))

CPU 消耗翻倍,但内存使用量保持在看似长期稳定的状态。

【讨论】:

  • 是的,但是调用 System/gc 经常会导致程序真的很慢,所以我认为这不是一个真正的解决方案。 VM 应该自己处理 gc。
【解决方案2】:

我的结论是这个问题与 clojure eval 或 JVM 没有直接关系。它仅与 eclipse-逆时针和/或 leiningen-REPL 结合使用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-09-14
    • 1970-01-01
    • 2012-05-21
    • 1970-01-01
    • 1970-01-01
    • 2018-12-30
    • 1970-01-01
    相关资源
    最近更新 更多