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

Java:在不使用jmap或不挂起应用程序的情况下获取堆转储

阎英朗
2023-03-14

在少数情况下,我们的应用程序使用大约12 GB的内存。我们试图使用jmap实用程序获得堆转储。由于应用程序使用了一些GB的内存,它会导致应用程序停止响应,并导致生产中的问题。

在我们的例子中,堆的使用率在6小时内从2-3GB突然增加到12GB。为了发现内存使用趋势,我们尝试在重启应用程序后每一小时收集一次堆转储。但正如前面所说,由于使用jmap会导致应用程序挂起,我们需要重新启动它,我们无法了解内存使用的趋势。

是否有一种在不挂起应用程序的情况下获取堆转储的方法,或者是否有jmap以外的实用程序来收集堆转储。

对此高度赞赏的想法,因为如果没有内存使用的趋势,很难解决这个问题。

注意:我们的应用程序在CentOS中运行。

谢谢,阿伦

共有3个答案

连坚白
2023-03-14

您可以使用GDB来获取堆转储,而无需在目标VM上运行jmap,但是这仍然会挂起应用程序将堆转储写入磁盘所需的时间。假设磁盘速度为100MB/s(基本镜像数组或单个磁盘),这仍然是2分钟的停机时间。http://blogs.atlassian.com/2013/03/so-you-want-your-jvms-heap/

避免停止JVM的唯一真正方法是事务性内存和利用它提供进程快照功能的内核。这是STM支持者的梦想之一,但目前尚不可用。VMWare的热迁移非常接近,但这取决于您的分配速率不超过网络带宽,而且不会保存快照。请求他们为你添加它,这将是一个整洁的功能。

柳星晖
2023-03-14

首先,在执行线程转储/快照时冻结JVM是非常重要的。如果JVM能够在创建快照时继续运行,那么几乎不可能获得一致的快照。

那么,还有其他方法可以获得堆转储吗?

>

  • 您可以使用VisualVM获得堆转储,如下所述。

    您可以使用jconsole或Eclipse内存分析器获得堆转储,如下所述。

    但是所有这些都必然会导致JVM(至少)暂停。

    如果你的应用程序实际上是挂起的(永久的!),这听起来像是你的应用程序本身的问题。我的建议是在寻找存储泄漏之前看看你是否能找到这个问题。

    我的另一个建议是,查看单个堆转储,并使用统计数据来确定哪些类型的对象正在使用所有空间。。。以及为什么可以联系到它们。很可能你根本不需要“趋势”信息。

  • 胡鸿志
    2023-03-14

    试试下面的,它是JDK自带的

    /usr/lib/jvm/jdk-YOUR-VERSION/bin/jcmd PID GC.heap_dump FILE-PATH-TO-SAVE
    

    例子:

    /usr/lib/jvm/jdk1.8.0_91/bin/jcmd 25092 GC.heap_dump /opt/hd/3-19.11-jcmd.hprof
    

    这个倾销过程比用jmap倾销快得多!转储文件要小得多,但它足以让您了解泄漏的位置。

    在撰写此答案时,内存分析器和IBM HeapAnalyzer存在一些错误,它们无法从jmap读取转储文件(jdk8,大文件)。你可以用你的工具包来读取这些文件。

     类似资料:
    • 首先,如果这是一个很长的代码段,我很抱歉,但是,我想做一个模态窗口,它将你在我的用户表单中写的东西写下来,并要求你确认它。我目前正在学习Javascript,我不允许使用innerHTML,我必须动态地编写“名字”等(名字的文本),不允许只在弹出窗口内写它。我已经让大多数东西工作,但“名字”“名字”等显示为“未定义”,或者(正如你可以看到的,我在这种情况下只用名字尝试的事情)显示为“空”。 希望有

    • 问题内容: 如何在Java程序中打开和关闭调试?如何在不重新编译Java程序的情况下打开和关闭调试? 问题答案: 无需使用IDE进行调试 1)您可以使用Assertions编写Java程序。您随时可以启用/禁用它们。 2)您可以使用配置了log4j.properties的日志。在Java程序中,您可以随时指定信息和调试日志,只要您想显示调试或信息日志等信息,就可以在log4j.properties

    • 问题内容: 我正在使用nodejs和expressjs框架从服务器下载文件’jsonFile.json’。 我正在使用以下代码 但这会导致对整个文件内容的响应。 我期望浏览器要我将文件保存在本地磁盘中。 如何将文件保存在本地磁盘中? 问题答案: 让Express设置正确的标头,然后执行以下操作: (doc) 编辑: 由于您是通过AJAX调用进行请求的,因此您必须更改设置,因为大多数(全部?)浏览器

    • 任何建议什么将是实施这种行为的最佳方式。 谢谢Bsengar

    • 问题内容: 我正在运行jstat -gc(来自OpenJDK): 如何阅读: 用过的堆 堆大小 最大堆 从此输出,就像VisualVM所示? 问题答案: 有关一般参考,请参见https://docs.oracle.com/javase/8/docs/technotes/tools/unix/jstat.html。 当前堆大小将是所有以“ C”结尾的字段的总和-S0C,S1C,EC,OC(Metas

    • 问题内容: 通常,要将调试器附加到正在运行的jvm,您需要使用以下参数启动jvm: 现在,如果我要调试不是在调试模式下启动的进程,该怎么办? 当生产系统(即在没有调试args的情况下启动)显示“随机”(我用宽松的术语)错误时,就会出现这种情况。因此,我无法使用适当的参数重新启动jvm,因为没人知道如何再次再现该错误。在这种情况下是否不可能附加到JVM? 只是为了澄清,除非将它们以调试方式启动,否则