首页  >  文章  >  Java  >  使用 VisualVM 和 jstack 调试和监控 Java 应用程序

使用 VisualVM 和 jstack 调试和监控 Java 应用程序

DDD
DDD原创
2024-11-07 08:37:02114浏览

Java 应用程序,尤其是在生产中运行的应用程序,可能会出现性能瓶颈死锁内存泄漏,这些可能难以追踪。当出现这些问题时,快速有效的调试对于保持应用程序平稳运行并保持积极的用户体验至关重要。这就是 VisualVM 和 JStack 成为 Java 开发人员宝贵工具的地方。

VisualVM 具有强大的分析和监控功能,jstack 提供详细的线程转储,这是一个动态组合,使开发人员能够检测、诊断和调试复杂问题轻松。

诊断和解决死锁至关重要,尤其是在高性能应用程序中。本指南将探讨如何使用两个强大的 Java 工具检测死锁并获取线程转储VisualVMjstack

1.了解死锁和线程转储

在深入了解这些工具之前,让我们先澄清一些基础知识:

死锁:线程互相等待对方释放资源,导致无限阻塞循环的情况。

线程转储:给定时间 Java 应用程序中活动线程的快照,包括其状态以及它们持有或等待的任何锁的详细信息。线程转储对于分析和识别 Java 应用程序中的死锁源至关重要,它使开发人员能够查明线程阻塞的原因。

2. VisualVM简介

VisualVM 是一个集成了多个命令行 JDK 工具的可视化工具,可提供 Java 应用程序的全面概述。它广泛用于监控和分析应用程序、诊断内存泄漏以及分析性能。

主要特点

  • 实时监控和分析
  • 线程分析
  • 内存和 CPU 使用情况洞察
  • 用于死锁分析的线程转储

使用 VisualVM 进行调试(适用于 Java 应用程序)

  • 下载 VisualVM
  • 打开 VisualVM。
  • 连接到正在运行的 JVM 进程。
    Debug and Monitor Java App with VisualVM and jstack

  • 在监控工具中,您可以点击Thread Dump或者实时查看线程详细信息。

Debug and Monitor Java App with VisualVM and jstack

Debug and Monitor Java App with VisualVM and jstack

3.jstack简介

jstack 对于任何处理严重依赖线程的复杂应用程序的 Java 开发人员来说都是一个非常宝贵的命令行工具。通过提供对线程状态、锁定行为和执行流程的详细了解,jstack 简化了调试过程,使其更容易发现和解决死锁、性能瓶颈和应用程序冻结等问题。

主要特点

  • jstack 显示每个线程的状态,例如 RUNNABLEBLOCKEDWAITINGTIMED_WAITING
  • 捕获活动或挂起进程的堆栈跟踪,以帮助调试复杂的线程问题。
  • jstack 在线程转储中标记死锁线程,以便您快速识别它们。
  • 获取线程转储,其中列出了 JVM 中的所有活动线程。
  • VisualVMjmap 等其他工具配合使用,jstack 可以帮助将内存泄漏追溯到负责过多对象创建或保留引用的线程。
  • 通过分析线程转储,开发人员可以识别有问题的同步、过度阻塞或减少争用的机会,从而提高并发性和响应能力。

使用jstack获取和分析线程转储

要使用 jstack 捕获正在运行的 Java 应用程序的线程转储,您需要 Java 进程的进程 ID (PID)。这是分步指南:

  • 第 1 步: 查找 Java 应用程序的进程 ID (PID)
C:\Program Files\Java\jdk-21\bin>jps -l
12912
22480 org.springframework.ide.vscode.boot.app.BootLanguageServerBootApp
24020 jdk.jcmd/sun.tools.jps.Jps
14344 org/netbeans/Main
21944 deadlock/deadlock.DeadlockExample
  • 第 2 步: 使用 jstack 捕获线程转储
C:\Program Files\Java\jdk-21\bin>jstack 21944
2024-11-02 11:12:18
Full thread dump Java HotSpot(TM) 64-Bit Server VM (21.0.5+9-LTS-239 mixed mode, sharing):

Threads class SMR info:
.
..
....
...

"Thread-0" #29 [18484] prio=5 os_prio=0 cpu=0.00ms elapsed=1896.34s tid=0x000001bb3395ac40 nid=18484 waiting for monitor entry  [0x00000099227ff000]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at deadlock.DeadlockExample.lambda(deadlock/DeadlockExample.java:23)
        - waiting to lock <0x000000070d03c740> (a java.lang.Object)
        - locked <0x000000070d05a828> (a java.lang.Object)
        at deadlock.DeadlockExample$$Lambda/0x000001bb350019f8.run(deadlock/Unknown Source)
        at java.lang.Thread.runWith(java.base@21.0.5/Thread.java:1596)
        at java.lang.Thread.run(java.base@21.0.5/Thread.java:1583)

"Thread-1" #30 [23240] prio=5 os_prio=0 cpu=0.00ms elapsed=1896.34s tid=0x000001bb3395b2a0 nid=23240 waiting for monitor entry  [0x00000099228ff000]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at deadlock.DeadlockExample.lambda(deadlock/DeadlockExample.java:41)
        - waiting to lock <0x000000070d05a828> (a java.lang.Object)
        - locked <0x000000070d03c740> (a java.lang.Object)
        at deadlock.DeadlockExample$$Lambda/0x000001bb35001c08.run(deadlock/Unknown Source)
        at java.lang.Thread.runWith(java.base@21.0.5/Thread.java:1596)
        at java.lang.Thread.run(java.base@21.0.5/Thread.java:1583)

...
.....
..
Found one Java-level deadlock:
=============================
"Thread-0":
  waiting to lock monitor 0x000001bb117727a0 (object 0x000000070d03c740, a java.lang.Object),
  which is held by "Thread-1"

"Thread-1":
  waiting to lock monitor 0x000001bb11772500 (object 0x000000070d05a828, a java.lang.Object),
  which is held by "Thread-0"

Java stack information for the threads listed above:
===================================================
"Thread-0":
        at deadlock.DeadlockExample.lambda(deadlock/DeadlockExample.java:23)
        - waiting to lock <0x000000070d03c740> (a java.lang.Object)
        - locked <0x000000070d05a828> (a java.lang.Object)
        at deadlock.DeadlockExample$$Lambda/0x000001bb350019f8.run(deadlock/Unknown Source)
        at java.lang.Thread.runWith(java.base@21.0.5/Thread.java:1596)
        at java.lang.Thread.run(java.base@21.0.5/Thread.java:1583)
"Thread-1":
        at deadlock.DeadlockExample.lambda(deadlock/DeadlockExample.java:41)
        - waiting to lock <0x000000070d05a828> (a java.lang.Object)
        - locked <0x000000070d03c740> (a java.lang.Object)
        at deadlock.DeadlockExample$$Lambda/0x000001bb35001c08.run(deadlock/Unknown Source)
        at java.lang.Thread.runWith(java.base@21.0.5/Thread.java:1596)
        at java.lang.Thread.run(java.base@21.0.5/Thread.java:1583)

Found 1 deadlock.

笔记

  • jstack 在 JDK 中可用,因此请确保 JDK 已安装并在您的环境中可访问。
  • 在某些系统上使用jstack可能需要管理员权限。
  • 使用 jstack -l 12345 > threaddump.txt 将线程转储保存到名为 threaddump.txt 的文件中。

尾奏

VisualVMjstack 是 Java 开发人员工具包中用于诊断和排除 Java 应用程序故障的两个重要工具,特别是在处理性能问题、死锁和线程瓶颈时。

VisualVMjstack 共同提供了调试 Java 应用程序的全面方法,其中 VisualVM 提供广泛的实时性能洞察,jstack 启用深度线程级分析。它们的组合使用使开发人员能够在开发和生产环境中有效地诊断和解决复杂的 Java 问题。

参考

非常感谢在线文档、社区和所有可用资源,使本文成为可能。

  1. 如何使用 VisualVM
  2. 多线程概念第 1 部分:原子性和不变性
  3. Java VisualVM

以上是使用 VisualVM 和 jstack 调试和监控 Java 应用程序的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn