如何在Clojure + JVM 1.8中查找内存“泄漏”

4
我的Clojure应用在运行Java 8的Linux系统上表现出奇怪的行为。具体而言,当使用httpkit通过WebSockets与客户端通信时,内存占用似乎无限增长 - 取决于系统,进程可能会被操作系统终止。

我查看了jconsole中的内存使用情况,并且显然是(新的)元空间不断增长。我通过向jar传递-XX:MaxMetaspaceSize=128m来解决了这个问题:在这种情况下,每当超过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))
      ; ...
    ))))

系统:

  • Ubuntu 14.04
  • OpenJDK Runtime Environment (版本1.8.0_40-internal-b27)
  • 6GB内存
  • Clojure 1.6.0
  • http-kit 2.1.6

在一台目前无法访问的CentOS上,同样的JVM表现出类似的行为,因此无法提供详细的规格。


2
jvisualvm 是 jconsole 所提供功能的超集,我曾经使用它成功地进行资源分配分析。 - noisesmith
谢谢你的提示。不幸的是,最新版本的jvisualvm在分析Clojure应用程序的内存使用时会冻结/崩溃。如果我只是采样内存使用情况,我得不到任何可以追踪到代码特定部分的信息。 - pholz
正如jstaffans所提到的,打开一个jmx连接会有所帮助(可以使用:jvm-opts ["-agentlib:jdwp=transport=dt_socket"]来完成)。 - noisesmith
2个回答

2

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

我以前也遇到过VisualVM冻结的问题。您可以尝试使用JMX连接,即使用JMX代理启动应用程序,并从VisualVM连接到它,就像它是远程的一样。有关更多信息,请参见文档

话虽如此,我认为YourKit是一款更优秀的分析软件。


JMX本地连接仍然表现出相同的行为,但YourKit运行得非常好。原来如此。 - pholz
泄漏发生在其他地方。 - pholz
@pholz,我遇到了类似的问题...您有关于如何解决泄漏的任何信息吗?我也需要找出它发生的位置。 - JMac

2
据我所知,最好的Java内存分析工具是Memory Analyzer。它是免费的、快速的。如果我们给它足够的内存,它甚至可以用来分析大堆内存,比如30g。请注意,保留HTML标签,不做任何修改。

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