目前我正在尝试解决Java内存问题: 我的 Java 应用程序不断使用越来越多的内存和 最终它被Linux OOM杀手杀死。
可能存在本机内存泄漏,因为经过检查 带有 VisualVM 的 JVM 的元空间和堆看起来都不错。
使用 top 命令我可以看到 JVM 使用的内存 不断增加。
本文中的第一个图形:
示例 #1
与我在自己的应用程序中看到的内容完美匹配。
所以我尝试使用 JeMalloc 来查找泄漏,如各种文章中所述。 在这里我遇到了一个问题:使用 jeprof 命令及更高版本时 Jeprof 本身的 top 命令,它确实显示了使用 内存最多,但这些是十六进制地址,所以我必须 缺少一些符号。但我不知道我需要哪些包裹,这对我来说是未知的。
我已经找到了这个链接: 链接 #1
并安装了这个软件包: debuginfo-install java-1.8.0-openjdk
我尝试先完成简单的步骤:
让 JeMalloc 使用一个简单的应用程序,例如 w。 接下来让它与java版本一起工作。 到目前为止一切顺利,我还可以从JeMalloc获得具有完美概述的PDF。
接下来让它与java -jar simpletest一起工作.jar <<在这里我缺少符号 例如,如果我不在此处关闭GZipInputStream,则不会显示在JeMalloc结果中。
接下来让它与java -jar myapplication一起工作.jar <<在这里我也缺少符号。
所以我的问题基本上是: 我需要什么软件包才能让 JeMalloc 显示所有符号名称来调试应用程序,例如:
public void test1() {
InputStream fileInputStream = null;
GZipInputStream gzipInputStream = null;
try {
fileInputStream = new FileInputStream("test.zip");
gzipInputStream = new GZIPInputStream(fileInputStream);
int data = gzipInputStream.read();
while (data != -1) {
// do something with data
data = gzipInputStream.read();
}
} catch (Exception ex) {
} finally {
// Disabled to see whether JeMalloc can detect the leak
/*try {
if (gzipInputStream != null) {
gzipInputStream.close();
}
if (fileInputStream != null) {
fileInputStream.close();
}
gzipInputStream = null;
fileInputStream = null;
} catch (IOException e) {
e.printStackTrace();
}*/
}
}
使用以下软件:
- Linux CentOS 7
- 杰马洛克
- OpenJDK
找到的文章:
文章 #1
文章 #2
文章 #3
文章 #4
替换分配器(例如使用 jemalloc 或 tcmalloc(来分析内存使用情况可能会提供有关本机内存泄漏源的提示,但它仅限于 JVM 中加载的库中可用的本机代码符号。
要在堆栈跟踪中使用 Java 类/方法,需要生成一个映射文件,将本机代码内存位置与其源相关联。撰写本文时唯一的工具是 https://github.com/jvm-profiling-tools/perf-map-agent
为了在堆栈中获取不仅仅是"解释器"名称,相关代码必须进行 JIT 编译,因此在 JVM 命令行选项上使用-XX:CompileThreshold=1
强制执行很有趣(在生产 IMO 中除外(。
在 JVM 中加载代理、生成映射文件和对代码进行 JIT 编译时,perf
可用于报告 CPU 分析。内存泄漏调查需要更多的处理。
最好的选择是获取bcc
及其memleak
工具,如果你的 Linux 内核是 4.9 或更高版本:https://github.com/iovisor/bcc/blob/master/tools/memleak_example.txt
非常感谢布伦丹·格雷格
Debian 系统在一个简单的apt install bcc
后就准备好了,但 RedHat 系统需要更多的工作,正如 CentOS 7 在 http://hydandata.org/installing-ebpf-tools-bcc-and-ply-on-centos-7 上记录的那样(在 CentOS 6 上更糟(
作为替代方案,perf
only也可以报告特定探头的泄漏堆栈跟踪。脚本和示例用法可在 https://github.com/dkogan/memory_leak_instrumentation 获得,但必须适应 Java 上下文。