当前位置: 首页 > 知识库问答 >
问题:

解释jemaloc数据可能发生堆外泄漏

越伟泽
2023-03-14

我在两周前开始搜索不断增长的java内存。我使用以下命令来防止堆增长过多,并进行一些调试

我使用oracle java 8在Ubuntu 16.04上运行,因为openjdk 8没有使jemaloc提供正确数据所需的调试符号

-XX:NativeMemoryTracking=detail -XX:+UseG1GC -XX:+UseStringDeduplication -Xms64m -Xmx256m -XX:MaxMetaspaceSize=128m -Xss256k

如您所见,我的Xmx设置为256m。然而top当前显示我的进程为1.1G

在使用了JProfiler和JVisualVm I以及我在谷歌上可以找到的许多其他东西之后,我得出结论,这一定是一个堆外问题。

经过多次搜索,我遇到了jemaloc,我读到的关于它的文章似乎很有希望。但是我现在在解释这些数据时遇到了一些问题。并找出如何找到问题的根源。

最高内存使用率

jemaloc图

本机内存跟踪数据

Native Memory Tracking:

Total: reserved=1678MB, committed=498MB
-                 Java Heap (reserved=256MB, committed=256MB)
                            (mmap: reserved=256MB, committed=256MB)

-                     Class (reserved=1103MB, committed=89MB)
                            (classes #14604)
                            (malloc=3MB #32346)
                            (mmap: reserved=1100MB, committed=85MB)

-                    Thread (reserved=26MB, committed=26MB)
                            (thread #53)
                            (stack: reserved=26MB, committed=26MB)

-                      Code (reserved=261MB, committed=96MB)
                            (malloc=17MB #17740)
                            (mmap: reserved=244MB, committed=79MB)

-                        GC (reserved=1MB, committed=1MB)
                            (mmap: reserved=1MB, committed=1MB)

-                  Internal (reserved=6MB, committed=6MB)
                            (malloc=6MB #48332)

-                    Symbol (reserved=19MB, committed=19MB)
                            (malloc=16MB #168491)
                            (arena=4MB #1)

-    Native Memory Tracking (reserved=5MB, committed=5MB)
                            (tracking overhead=4MB)

共有1个答案

毋宏茂
2023-03-14

本机内存跟踪只考虑Java虚拟机的结构,但不计算内存映射文件,也不计算共享库分配的本机内存(包括Java类库的本机代码)。此外,NMT不会跟踪malloc-标准libc分配器的任何内部碎片。

首先,要分析Java进程的堆外使用情况,请查看其完整内存映射:

pmap -X <pid>

这将揭示内存是由映射文件使用还是由匿名区域使用。

如果你看到一些匿名区域的容量达到64MB,这可能是malloc arenas的标志。众所周知,Libc malloc在某些系统上存在过度使用虚拟内存的问题。在这种情况下,使用jemalloctcmalloc作为替代品(即使没有评测功能)可能成为一种解决方案。

不幸的是,jemalloc profiler对Java一无所知;该图在最后一个本机函数处中断,因此输出可能会令人困惑。在您的案例中,jemalloc建议问题可能与类加载和系统有关。loadLibrary,但如果没有完整的图片,很难确定。

Async profiler允许在Java上下文中跟踪本机分配。跑

./profiler.sh -d <duration> -e malloc -f malloc.svg <pid>

这将产生一个火焰图的malloc调用,例如:

这只是一个演示如何java的示例。util。拉链GZIPOutputStream可以是本机内存分配的来源。当然,你的情况会有所不同。

请注意,malloc调用本身并不意味着内存泄漏。例如,内存可以被分配,然后很快释放。图表只是一个提示。

为了找到RSS增加的地方,您可能需要跟踪mprotectmmap调用。这可以通过类似的方式使用async profiler完成:

./profiler.sh -d <duration> -e mprotect -f mprotect.svg <pid>
./profiler.sh -d <duration> -e mmap -f mmap.svg <pid>

我注意到cbClassPrepareclassTrack\u process在jemalloc图中卸载了函数。这意味着您正在使用jdwp调试代理。这肯定是内存分配过多的一个原因——我以前经常在jdwp中看到内存泄漏。通过-agentlib-agentpath-javaagent选项启用的任何其他代理库也是可疑的,因为JVM不会跟踪它们的本机内存使用情况。

 类似资料:
  • 我一直在研究的一个应用程序显示了大量的堆外内存使用情况。 我已经将应用程序配置为使用4096M的Xms和Xmx。但是,在PID上运行会发现进程占用机器内存的9.6%(64GB机器->6.14G应用程序占用空间)。实例存活的时间越长,这种情况似乎就会无限制地增长。驻留尺寸约为5.9g。使用jvisualvm检查流程,我看到堆的使用量约为1.5GB,并且具有健康的GC模式。我已经拉了堆转储和线程转储,

  • 问题内容: 假设您有以下代码: 重用ps变量是否有潜在的泄漏? 如果是这样,我不希望声明多个此类准备好的语句(ps1,ps2,ps3等)。我应该如何重构呢? 有人在想吗? 编辑 收到几个答案,说明这无关紧要。我想指出的是,我遇到的游标保持打开状态的时间过长,并且想知道该模式是否与此有关。 我的想法是: 第一条语句被取消引用并进行了GC处理,因此在此示例中,如何关闭第一个PreparedStatem

  • 问题内容: 当tomcat关闭时,我在catalina.out日志文件中收到以下消息。我正在使用Tomcat 7.x和Tomcat JDBC数据源。 第一个声称DataSource已被强制取消注册,这样很好。但是,这很奇怪,因为我已经像这样配置了destroy-method: 不知道为什么我得到第二个。关于“ MySQL语句取消计时器”的内容。 任何帮助表示赞赏 编辑1:我尝试了@Zelldon建

  • 这是我的代码: 我怎么纠正这个?

  • 我的项目中有一个AsyncTask,有一个警告,它说:

  • 我正在开发一个带有服务的Android 2.3.3应用程序。我在服务中有以下内容与主要活动进行通信: 在这里,,我得到以下Lint警告: