如何在 clojure + jvm 1.8 中查找内存 "leaks"

How to find memory "leaks" in clojure + jvm 1.8

我的 clojure 应用程序在 linux 系统上表现出奇怪的行为 运行 java 8. 具体来说,当使用 httpkit 通过 websockets 与客户端通信时,内存占用显然无限制地增长 - 根据系统的不同,进程随后被 OS.

杀死

我查看了 jconsole 中的内存使用情况,显然是(新)元空间 在不断增长。我设法通过将 -XX:MaxMetaspaceSize=128m 传递给 jar 来抑制问题:在这种情况下,元空间内存图在超过 128m 时会下降,并且程序不会最终吃掉所有内存。但这是一种解决方法——我想了解为什么会出现这种增长,但我不确定如何进行。在 C++ 中,我会使用 valgrind 追踪泄漏,但由于 Java/Clojure 是垃圾收集的,我不确定要寻找什么。

我不是 100% 确定它只是 httpkit 代码部分,但从我的测试来看它似乎是 - 这是一段代码摘录,我在其中收听消息并根据消息发回json 包含一些数据的对象; coreparams-atom 预计任何时候都有大约 10 个浮动条目。

(httpkit/on-receive channel (fn [data]
  (let [data-map (json/read-str data)
        param (first (get data-map "data"))
        value (second (get data-map "data"))]
    (case (get data-map "type")
      ; ...
      "curparams" (let [tosend (json/write-str 
                                 {:type "curparams"
                                  :data (-> @state/coreparams-atom
                                            (assoc :timestamp (db/timestamp))
                                            (util/keyword-replace-char ":" "_"))})]
                    (httpkit/send! channel tosend))
      ; ...
    ))))

系统:

CentOS 上同一 JVM 的类似行为,我目前无法访问,因此无法提供详细规格。

内存采样(使用 VisualVM 或其他工具,例如 YourKit)通常会指出问题的大致方向。例如,它可以告诉您 类 属于哪些包导致内存泄漏。之后您可以进行更详细的分析。

我也 运行 遇到过 VisualVM 冻结的问题。您可以尝试的一件事是使用 JMX 连接,即您使用 JMX 代理启动您的应用程序并从 VisualVM 连接到它,就好像它是远程的一样。有关详细信息,请参阅 the docs

也就是说,在我看来,YourKit 是一款非常出色的分析软件。

据我所知,最好的 java 内存分析器工具是 Memory Analyzer。它是免费的,速度很快。它甚至可以用来分析大堆,例如30g,如果我们给它足够的内存。