如何在 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))
; ...
))))
系统:
- Ubuntu 14.04
- OpenJDK 运行时环境(构建
1.8.0_40-internal-b27)
- 6GB 内存
- Clojure 1.6.0
- http-kit 2.1.6
CentOS 上同一 JVM 的类似行为,我目前无法访问,因此无法提供详细规格。
内存采样(使用 VisualVM 或其他工具,例如 YourKit)通常会指出问题的大致方向。例如,它可以告诉您 类 属于哪些包导致内存泄漏。之后您可以进行更详细的分析。
我也 运行 遇到过 VisualVM 冻结的问题。您可以尝试的一件事是使用 JMX 连接,即您使用 JMX 代理启动您的应用程序并从 VisualVM 连接到它,就好像它是远程的一样。有关详细信息,请参阅 the docs。
也就是说,在我看来,YourKit 是一款非常出色的分析软件。
据我所知,最好的 java 内存分析器工具是 Memory Analyzer。它是免费的,速度很快。它甚至可以用来分析大堆,例如30g,如果我们给它足够的内存。
我的 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))
; ...
))))
系统:
- Ubuntu 14.04
- OpenJDK 运行时环境(构建 1.8.0_40-internal-b27)
- 6GB 内存
- Clojure 1.6.0
- http-kit 2.1.6
CentOS 上同一 JVM 的类似行为,我目前无法访问,因此无法提供详细规格。
内存采样(使用 VisualVM 或其他工具,例如 YourKit)通常会指出问题的大致方向。例如,它可以告诉您 类 属于哪些包导致内存泄漏。之后您可以进行更详细的分析。
我也 运行 遇到过 VisualVM 冻结的问题。您可以尝试的一件事是使用 JMX 连接,即您使用 JMX 代理启动您的应用程序并从 VisualVM 连接到它,就好像它是远程的一样。有关详细信息,请参阅 the docs。
也就是说,在我看来,YourKit 是一款非常出色的分析软件。
据我所知,最好的 java 内存分析器工具是 Memory Analyzer。它是免费的,速度很快。它甚至可以用来分析大堆,例如30g,如果我们给它足够的内存。