性能监控之常见 Java Heap Dump 方法

简介: 【6月更文挑战8天】性能监控之常见 Java Heap Dump 方法

一、前言

在本文中,我们总结下 Java dump 的几种不同方法。

Java Heap Dump 是特定时刻 JVM 内存中所有对象的快照。它们对于解决内存泄漏问题和分析 Java 应用程序中的内存使用情况非常有用。

Java Heap Dump 通常以二进制格式的 hprof 文件存储。我们可以使用 jhat 或 JVisualVM 之类的工具打开和分析这些文件。同样,使用 MAT 工具分析是很常见的。

二、JDK 工具包

JDK 附带了几个以不同方式 Heap Dump 的工具。所有这些工具都位于 JDK 主目录下的 bin 文件夹下。因此,只要这个目录包含在系统路径中,我们就可以直接从命令行启动它们。

1、jmap

jmap 是一种工具,用于打印有关正在运行的 JVM 中的内存的统计信息。我们可以将其用于本地或远端进程。

要使用 Jmap Heap Dump ,我们需要使用 Heap Dump 参数:

jmap -dump:[live],format=b,file=<file-path> <pid>

与该参数一起,我们应该指定几个参数:

  • live:如果设置,则仅打印具有活动引用的对象,并丢弃准备好进行垃圾回收的对象。此参数是可选的。
  • format = b:指定转储文件将采用二进制格式。如果未设置,结果是相同的
  • file:将写入的文件
  • pid:Java 进程的 ID

举一个例子是这样的:

jmap -dump:live,format=b,file=/tmp/dump.hprof 12587

注意:
我们可以使用 jps 命令轻松获取 Java 进程的pid。
jmap 是作为实验工具在 JDK 中引入的。因此,在某些不支持的情况下,最好使用其他工具代替。

2、jcmd

jcmd 是一个非常完整的工具,可以通过向 JVM 发送命令请求来工作。我们必须在运行 Java 进程的同一台机器上使用它。

它的最多命令就是 GC.heap_dump,我们可以通过指定进程的 pid 和输出文件路径来使用它来 Heap Dump:

jcmd <pid> GC.heap_dump <file-path>

我们可以使用上面例子中使用的相同参数执行它:

jcmd 12587 GC.heap_dump /tmp/dump.hprof

与 jmap 一样,生成的 dump 为二进制格式。

3、JVisualVM

JVisualVM 是带有图形用户界面的工具,它使我们可以监控 Java 应用程序,对其进行故障排除和分析。GUI 简单,直观并且易于使用。

我们可以右键单击 Java 进程并选择“线程dump”选项,该工具将创建 dump 并在新选项卡中将其打开:

image.png

注意:
我们可以在“基本信息” 部分中找到创建的文件的路径。
从 JDK 9开始,Visual VM 不包括在 Oracle JDK 和 Open JDK 发行版中。因此,如果我们使用的是 Java 9 或更高版本,则可以从 Visual VM 开源项目站点获得 JVisualVM 。
地址:https://visualvm.github.io/

三、自动 heap dump

上面介绍所有工具均在特定时间手动去 dump 的。在某些情况下,我们希望在发生 java.lang.OutOfMemoryError 时获取 Heap Dump ,以帮助我们分析问题。

对于这种情况,Java 提供了 HeapDumpOnOutOfMemoryError 命令行参数,当抛出 java.lang.OutOfMemoryError 时,程序会生成 heap dump :

java -XX:+HeapDumpOnOutOfMemoryError

默认情况下,它将 dump 存储在我们正在运行应用程序的目录中的 java_pid <pid> .hprof 文件中。如果要指定另一个文件或目录,可以在 HeapDumpPath 参数中进行设置:

java -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=<file-or-dir-path>

使用此参数,当我们的应用程序内存不足时,我们将能够在日志中看到包含 dump 的已创建文件:

java.lang.OutOfMemoryError: Requested array size exceeds VM limit
Dumping heap to java_pid12587.hprof ...
Exception in thread "main" Heap dump file created [4744371 bytes in 0.029 secs]
java.lang.OutOfMemoryError: Requested array size exceeds VM limit
    at com.baeldung.heapdump.App.main(App.java:7)

在上面的示例中,它已写入到 java_pid12587.hprof 文件中。

就像我们看到的,此参数非常有用,使用此参数运行应用程序时没有任何开销。因此,强烈建议始终使用此参数,尤其是在生产中。

最后,还可以在运行时通过使用 HotSpotDiagnostic MBean 来指定此参数。
为此,我们可以使用 JConsole 工具并将HeapDumpOnOutOfMemoryError VM 参数值设置为 true:
image.png

四、JMX

我们将使用在上一节中简要介绍的 HotSpotDiagnostic MBean。该 MBean 提供了一个 dumpHeap 方法,该方法接受 2 个参数:

  • outputFile:dump 文件的路径。该文件应具有 hprof 扩展名
  • live:如果设置为 true,则它仅 dump 内存中的活动对象,就像我们之前在 jmap上看到的那样

下面我们将介绍两种不同的方法来调用此方法来 heap dump。

1、JConsole

使用 HotSpotDiagnostic MBean 的最简单方法是使用 JMX 客户端(例如JConsole)

打开 JConsole 并连接到正在运行的 Java 进程,则可以导航到 MBeans 选项卡并在 com.sun.management下找到HotSpotDiagnostic。
在操作中,我们可以找到我们之前描述的 dumpHeap 方法:
image.png

如所示,为了执行 dumpHeap 操作,我们只需要引入参数 outputFile 并将其存在于 p0 和 p1 文本字段中。

2、编程

使用 HotSpotDiagnostic MBean 的另一种方法是通过从 Java 编程方式调用它。

为此,我们首先需要获取一个 MBeanServer 实例,以便获取在应用程序中注册的 MBean。
之后,我们只需要获取 HotSpotDiagnosticMXBean 的实例 并调用其 dumpHeap 方法。

import javax.management.MBeanServer;

import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.nio.file.Paths;

public class HeapDump {
   
   

    public static void dumpHeap(String filePath, boolean live) throws IOException {
   
   
        MBeanServer server = ManagementFactory.getPlatformMBeanServer();
        HotSpotDiagnosticMXBean mxBean = ManagementFactory.newPlatformMXBeanProxy(
          server, "com.sun.management:type=HotSpotDiagnostic", HotSpotDiagnosticMXBean.class);
        mxBean.dumpHeap(filePath, live);
    }

    public static void main(String[] args) throws IOException {
   
   
        String file = Paths.get("dump.hprof").toFile().getPath();

        dumpHeap(file, true);
    }
}

注意,不能覆盖 hprof 文件。因此,在创建打印 heap dumps 的应用程序时应该考虑到这一点。如果我们没有这样做,就会得到一个异常:

Exception in thread "main" java.io.IOException: File exists
    at sun.management.HotSpotDiagnostic.dumpHeap0(Native Method)
    at sun.management.HotSpotDiagnostic.dumpHeap(HotSpotDiagnostic.java:60)

五、Arthas

Arthas 是阿里提供的一款 Java 开源诊断工具。能够查看应用的线程状态、JVM 信息等;并能够在线对业务问题诊断,比如查看方法调用的出入参、执行过程、抛出的异常、输出方法执行耗时等,大大提升了线上问题的排查效率。

Arthas 提供 heapdump 命令:dump java heap, 类似 jmap命令的 heap dump功能。

dump 到指定文件:

[arthas@58205]$ heapdump /tmp/dump.hprof
Dumping heap to /tmp/dump.hprof...
Heap dump file created

只 dump live对象:

[arthas@58205]$ heapdump --live /tmp/dump.hprof
Dumping heap to /tmp/dump.hprof...
Heap dump file created

dump 到临时文件:

[arthas@58205]$ heapdump
Dumping heap to /var/folders/my/wy7c9w9j5732xbkcyt1mb4g40000gp/T/heapdump2019-09-03-16-385121018449645518991.hprof...
Heap dump file created

更多参考:https://arthas.gitee.io/heapdump.html

六、结论

在本文中,我们展示了用 Java Heap Dump 的多种方法。

image.png

从经验上来说,我们应该记得在运行 Java 应用程序时始终使用 HeapDumpOnOutOfMemoryError 参数。

目录
相关文章
|
3月前
|
Java 开发者
Java 中的 toString() 方法详解:为什么它如此重要?
在Java开发中,`toString()`方法至关重要,用于返回对象的字符串表示。默认实现仅输出类名和哈希码,信息有限且不直观。通过重写`toString()`,可展示对象字段值,提升调试效率与代码可读性。借助Lombok的`@Data`注解,能自动生成标准化的`toString()`方法,简化开发流程,尤其适合字段较多的场景。合理运用`toString()`,可显著提高开发效率与代码质量。
161 0
|
1月前
|
人工智能 前端开发 Java
Java 面试资料中相关代码使用方法与组件封装方法解析
这是一份详尽的Java面试资料代码指南,涵盖使用方法与组件封装技巧。内容包括环境准备(JDK 8+、Maven/Gradle)、核心类示例(问题管理、学习进度跟踪)、Web应用部署(Spring Boot、前端框架)、单元测试及API封装。通过问题库管理、数据访问组件、学习进度服务和REST接口等模块化设计,帮助开发者高效组织与复用功能,同时支持扩展如用户认证、AI推荐等功能。适用于Java核心技术学习与面试备考,提升编程与设计能力。资源链接:[点此下载](https://pan.quark.cn/s/14fcf913bae6)。
64 6
Java 面试资料中相关代码使用方法与组件封装方法解析
|
2月前
|
JavaScript 前端开发 Java
Java 编程进阶实操中工具集整合组件封装方法与使用指南详解
本文详细介绍Hutool工具集和图书管理系统相关组件的封装方法及使用示例。通过通用工具类封装(如日期格式化、字符串处理、加密等)、数据库操作封装(结合Hutool DbUtil与MyBatis)、前端Vue组件封装(图书列表与借阅表单)以及后端服务层封装(业务逻辑实现与REST API设计),帮助开发者提升代码复用性与可维护性。同时,提供最佳实践建议,如单一职责原则、高内聚低耦合、参数配置化等,助力高效开发。适用于Java编程进阶学习与实际项目应用。
106 10
|
2月前
|
搜索推荐 Java 定位技术
Java实现利用GeoLite2-City.mmdb根据IP定位城市的方法
在城市,国家,地区等地理位置数据获取之后,你可以依指定的业务需求,来进行进一步的数据处理。例如,你可以设计一个应用,根据用户的 IP 地址来个性化地展示内容,或者用于分析网络请求的来源等。
329 20
|
2月前
|
Arthas 存储 监控
Arthas heapdump(dump java heap, 类似 jmap 命令的 heap dump 功能)
Arthas heapdump(dump java heap, 类似 jmap 命令的 heap dump 功能)
83 8
|
2月前
|
SQL Java 数据库连接
Java中实现SQL分页的方法
无论何种情况,选择适合自己的,理解了背后的工作原理,并能根据实际需求灵活变通的方式才是最重要的。
69 9
|
2月前
|
安全 Java API
【Java性能优化】Map.merge()方法:告别繁琐判空,3行代码搞定统计累加!
在日常开发中,我们经常需要对Map中的值进行累加统计。}else{代码冗长,重复调用get()方法需要显式处理null值非原子操作,多线程下不安全今天要介绍的方法,可以让你用一行代码优雅解决所有这些问题!方法的基本用法和优势与传统写法的对比分析多线程安全版本的实现Stream API的终极优化方案底层实现原理和性能优化建议一句话总结是Java 8为我们提供的Map操作利器,能让你的统计代码更简洁、更安全、更高效!// 合并两个列表});简单累加。
194 0
|
3月前
|
存储 Java 开发者
Java 中的 equals 方法:看似简单,实则深藏玄机
本文深入探讨了Java中`equals`方法的设计与实现。默认情况下,`equals`仅比较对象引用是否相同。以`String`类为例,其重写了`equals`方法,通过引用判断、类型检查、长度对比及字符逐一比对,确保内容相等的逻辑。文章还强调了`equals`方法需遵循的五大原则(自反性、对称性等),以及与`hashCode`的关系,避免集合操作中的潜在问题。最后,对比了`instanceof`和`getClass()`在类型判断中的优劣,并总结了正确重写`equals`方法的重要性,帮助开发者提升代码质量。
163 1
|
4月前
|
存储 JSON Java
《从头开始学java,一天一个知识点》之:方法定义与参数传递机制
**你是否也经历过这些崩溃瞬间?** - 看了三天教程,连`i++`和`++i`的区别都说不清 - 面试时被追问&quot;`a==b`和`equals()`的区别&quot;,大脑突然空白 - 写出的代码总是莫名报NPE,却不知道问题出在哪个运算符 🚀 这个系列就是为你打造的Java「速效救心丸」!我们承诺:每天1分钟,地铁通勤、午休间隙即可完成学习;直击痛点,只讲高频考点和实际开发中的「坑位」;拒绝臃肿,没有冗长概念堆砌,每篇都有可运行的代码标本。上篇:《输入与输出:Scanner与System类》 | 下篇剧透:《方法重载与可变参数》。
100 25
|
4月前
|
安全 IDE Java
重学Java基础篇—Java Object类常用方法深度解析
Java中,Object类作为所有类的超类,提供了多个核心方法以支持对象的基本行为。其中,`toString()`用于对象的字符串表示,重写时应包含关键信息;`equals()`与`hashCode()`需成对重写,确保对象等价判断的一致性;`getClass()`用于运行时类型识别;`clone()`实现对象复制,需区分浅拷贝与深拷贝;`wait()/notify()`支持线程协作。此外,`finalize()`已过时,建议使用更安全的资源管理方式。合理运用这些方法,并遵循最佳实践,可提升代码质量与健壮性。
117 1

热门文章

最新文章