Java常用工具使用方法

663 阅读27分钟

JMAP:

jmap 是 Java 提供的一个工具,用于生成 Java 堆内存的快照,并帮助分析堆的使用情况。它常用于诊断 Java 应用程序中的内存问题,如内存泄漏或性能问题。

jmap 常用步骤

  1. 查看所有 Java 进程

    使用 jmap 前,首先可以查看当前机器上所有运行的 Java 进程,获取目标进程的 PID(进程ID)。

    jps
    

    该命令会列出当前系统中所有运行的 Java 进程及其进程 ID。例如:

    12345 MyJavaApp
    

    这里 12345 是进程 ID。

  2. 生成堆转储(Heap Dump)

    使用 jmap 生成堆转储文件(heap dump),这是分析堆内存使用情况的重要工具。

    jmap -dump:live,format=b,file=heapdump.hprof <PID>
    
    • -dump:live:表示仅导出存活对象的堆信息。
    • format=b:表示以二进制格式导出堆信息。
    • file=heapdump.hprof:指定导出的堆转储文件的路径和名称。
    • <PID>:替换为目标 Java 进程的进程 ID。

    生成的堆转储文件 heapdump.hprof 可以使用分析工具(如 Eclipse Memory Analyzer Tool、VisualVM 等)进一步分析。

  3. 查看堆内存使用情况

    可以使用 jmap 查看堆内存的基本使用情况,比如查看堆的总大小、各个区域的大小、内存使用情况等。

    jmap -heap <PID>
    

    输出示例:

    Heap Configuration:
        MinHeapFreeRatio         = 40
        MaxHeapFreeRatio         = 70
        MaxHeapSize              = 2147483648 (2048.0MB)
        NewSize                  = 83886080 (80.0MB)
        MaxNewSize               = 2147483648 (2048.0MB)
        OldSize                  = 134217728 (128.0MB)
        NewRatio                 = 2
        SurvivorRatio            = 8
        MetaspaceSize            = 218103808 (208.0MB)
    

    该命令显示堆内存的配置和使用情况,例如年轻代、老年代、元空间的大小等。

  4. 查看堆中对象的详细信息

    使用 jmap -histo 可以查看堆中类的实例数量和内存占用。

    jmap -histo <PID>
    

    输出会列出堆内所有类的实例和占用的内存。例如:

    num     #instances         #bytes  class name
    ----------------------------------------------
    1:          9876         1556789  [C
    2:         12345         9876543  java.lang.String
    3:          4321         1234567  java.util.ArrayList
    ...
    

    这有助于查找占用大量内存的类和对象。

  5. 查看类的详细内存使用情况

    使用 jmap -F 可以强制执行一些操作,例如强制进行堆转储或强制查看堆内存。

    jmap -F -heap <PID>
    

    该命令在分析堆使用情况时可能有所帮助。

注意事项

  • 权限问题:通常需要以管理员权限运行 jmap,或者确保当前用户有足够的权限访问目标 Java 进程的内存。
  • 性能开销:生成堆转储或频繁查看堆内存会引入额外的性能开销,因此在生产环境中使用时应小心。
  • JVM参数:某些 JVM 参数(例如 -XX:+HeapDumpOnOutOfMemoryError)也能帮助在发生内存溢出时自动生成堆转储文件。

jstack

jstack 是 Java 提供的一个工具,用于生成 Java 应用程序的线程堆栈(Thread Dump)。它可以帮助你查看线程的执行状态,诊断死锁、线程挂起或性能问题等。

jstack 常用步骤

  1. 查看 Java 进程

    在使用 jstack 之前,首先需要查看当前机器上所有正在运行的 Java 进程,获取目标进程的 PID(进程 ID)。可以使用 jps 命令列出所有 Java 进程。

    jps
    

    该命令会列出当前系统中所有运行的 Java 进程及其进程 ID。例如:

    12345 MyJavaApp
    

    这里 12345 是 Java 应用程序的进程 ID(PID)。

  2. 生成线程堆栈(Thread Dump)

    使用 jstack 命令可以生成 Java 应用程序的线程堆栈信息。

    jstack <PID>
    
    • <PID>:替换为目标 Java 进程的进程 ID。

    该命令会输出所有线程的堆栈信息,包括每个线程的当前状态、正在执行的方法等。

    输出示例:

    "main" #1 prio=5 os_prio=0 tid=0x00007fbfc4004800 nid=0x4b03 waiting on condition [0x00007fbf88cfd000]
       java.lang.Thread.State: WAITING (on object monitor)
          at java.lang.Object.wait(Native Method)
          - waiting on <0x00000000f1cd9800> (a java.lang.Object)
          at java.lang.Object.wait(Object.java:502)
          at java.lang.Thread.join(Thread.java:1238)
          at com.example.MyApp.main(MyApp.java:15)
    

    该输出显示了线程的状态、调用栈以及锁的状态等信息。

  3. 将线程堆栈输出保存到文件

    如果堆栈信息较长,你可以将其输出保存到文件中,便于进一步分析。

    jstack <PID> > threaddump.txt
    

    这样线程堆栈信息就会被保存到 threaddump.txt 文件中,之后可以用文本编辑器查看或分析。

  4. 生成死锁(Deadlock)信息

    jstack 还可以用来检查死锁。死锁发生时,两个或多个线程互相等待对方释放资源,导致程序无法继续执行。使用 -l 选项可以显示死锁信息。

    jstack -l <PID>
    

    如果存在死锁,输出将包括死锁相关的信息,像下面这样:

    Found one Java-level deadlock:
    =============================
    "Thread-1" #15 prio=5 os_prio=0 tid=0x00007f12c480b800 nid=0x1e03 waiting for monitor entry
       at com.example.MyClass.method1(MyClass.java:42)
       - waiting to lock <0x000000078e5ab5a0> (a java.lang.Object)
       at com.example.MyClass.method2(MyClass.java:56)
       - locked <0x000000078e5ab5a0> (a java.lang.Object)
    "Thread-2" #16 prio=5 os_prio=0 tid=0x00007f12c480c000 nid=0x1e04 waiting for monitor entry
       at com.example.MyClass.method2(MyClass.java:56)
       - waiting to lock <0x000000078e5ab5a0> (a java.lang.Object)
       at com.example.MyClass.method1(MyClass.java:42)
       - locked <0x000000078e5ab5a0> (a java.lang.Object)
    

    输出中列出了参与死锁的线程,以及它们当前的堆栈信息。你可以根据这些信息来修复死锁问题。

  5. 分析线程堆栈信息

    生成线程堆栈后,分析堆栈信息非常重要。你需要检查每个线程的状态、调用栈,以及是否存在死锁或长时间运行的线程。以下是一些关键点:

    • 线程状态:检查线程是否处于 WAITINGTIMED_WAITINGBLOCKEDRUNNABLE 状态。
    • 死锁:如果多个线程在互相等待对方释放锁,则可能存在死锁。
    • CPU占用高:某些线程可能在耗费大量 CPU,长时间运行在同一个方法里。
  6. 分析线程状态

    线程堆栈的状态可以有以下几种:

    • NEW: 新创建的线程,尚未开始执行。
    • RUNNABLE: 线程正在执行(包括等待 CPU 时间)。
    • BLOCKED: 线程正在等待获取一个锁。
    • WAITING: 线程在等待某个条件发生。
    • TIMED_WAITING: 线程在等待一个特定时间后会自动唤醒。
    • TERMINATED: 线程已经结束执行。

    通过分析这些状态,可以帮助诊断应用程序的性能问题。

注意事项

  • 权限问题:你通常需要管理员权限或目标进程的用户权限才能使用 jstack 生成线程堆栈信息。
  • 生产环境使用小心:在生产环境中,生成线程堆栈会对应用程序的性能造成一定的影响,尤其是在高负载的情况下,因此使用时要小心。
  • 堆栈信息量大:线程堆栈信息可能非常庞大,分析时需要耐心。

Jstat

jstat 是 Java 提供的一个命令行工具,用于监控和分析 Java 虚拟机(JVM)的运行时统计信息。通过 jstat,你可以查看 JVM 各种性能指标,例如内存使用、垃圾回收、类加载、编译等。这对于性能调优和故障排查非常有帮助。

jstat 使用步骤

  1. 查看 JVM 进程的 PID

    在使用 jstat 之前,首先需要找出目标 JVM 进程的进程 ID(PID)。你可以通过 jps 命令来列出系统中所有的 Java 进程。

    jps
    

    该命令会列出当前系统上运行的所有 Java 进程。例如:

    12345 MyJavaApp
    

    这里 12345 就是 Java 应用程序的进程 ID(PID)。

  2. 查看 jstat 支持的选项

    jstat 命令有多个选项,可以用于查看不同的 JVM 统计信息。你可以通过 -help 参数来查看支持的选项和用法。

    jstat -help
    

    输出将列出所有可用的选项,例如:

    • -gc:显示垃圾回收信息。
    • -gcutil:显示垃圾回收的统计信息(百分比形式)。
    • -class:显示类加载信息。
    • -compiler:显示 JIT 编译器信息。
  3. 使用 jstat 命令查看 JVM 性能指标

    下面是一些常用的 jstat 命令示例。

    • 查看垃圾回收(GC)统计信息

      -gc 选项显示垃圾回收的详细信息,常用来检查堆内存使用情况。

      jstat -gc <PID> 1000
      

      其中:

      • <PID> 是目标 Java 进程的 PID。
      • 1000 是时间间隔(单位:毫秒),表示每 1000 毫秒打印一次 GC 信息。

      输出示例:

      S0C    S1C    S0U    S1U    EC     EU     OC     OU     MC     MU     CCSC   CCSU   YGC    YGCT   FGC    FGCT   GCT
      1024.0 1024.0 0.0    0.0    2048.0 1500.0 8192.0 5000.0 1024.0 500.0  1024.0 500.0  5      0.215  2      0.110  0.325
      

      每列的含义如下:

      • S0CS1C: Survivor 区域的容量。
      • S0US1U: Survivor 区域的已使用内存。
      • ECEU: Eden 区域的容量和已使用内存。
      • OCOU: Old 区域的容量和已使用内存。
      • MCMU: Metaspace 区域的容量和已使用内存。
      • CCSCCCSU:压缩类空间的容量和已使用内存。
      • YGCYGCT:年轻代垃圾回收次数和时间。
      • FGCFGCT:老年代垃圾回收次数和时间。
      • GCT:总垃圾回收时间。
    • 查看类加载信息

      -class 选项显示类加载器的相关信息。

      jstat -class <PID>
      

      输出示例:

      Loaded    Unloaded    Time
      2345      12          45.23
      
      • Loaded:加载的类数量。
      • Unloaded:卸载的类数量。
      • Time:类加载时间。
    • 查看 JIT 编译器信息

      -compiler 选项显示 JIT 编译器的信息,主要用来查看方法的编译情况。

      jstat -compiler <PID>
      

      输出示例:

      2345    12    45.23
      
    • 查看 Java 堆内存使用情况

      -gcutil 选项显示 JVM 堆内存的使用情况,通常用于监控垃圾回收的效果。

      jstat -gcutil <PID> 1000
      

      输出示例:

      S0    S1    E     O     M     CCS   YGC   YGCT   FGC   FGCT   GCT
      0.0   0.0   40.0  30.0  55.0  20.0  5     0.15   2     0.05   0.2
      

      各列代表:

      • S0S1:分别是 survivor 区的使用百分比。
      • E:Eden 区的使用百分比。
      • O:Old 区的使用百分比。
      • M:Metaspace 区的使用百分比。
      • CCS:压缩类空间的使用百分比。
      • YGCYGCT:年轻代垃圾回收次数和时间。
      • FGCFGCT:老年代垃圾回收次数和时间。
      • GCT:总垃圾回收时间。
  4. 常用选项总结

    以下是 jstat 的一些常用选项:

    • -gc:显示垃圾回收信息。
    • -gcutil:以百分比显示垃圾回收的统计信息。
    • -class:显示类加载信息。
    • -compiler:显示 JIT 编译器信息。
    • -printcompilation:显示已编译的代码。
  5. 分析 jstat 输出信息

    jstat 输出的统计数据可以帮助你了解 JVM 的内存使用情况,尤其是垃圾回收的行为。根据输出数据,你可以判断:

    • GC 是否频繁:频繁的 GC 可能表明堆内存不足或者对象创建过于频繁。
    • 内存是否有泄漏:长期不回收的内存可能是内存泄漏的征兆。
    • JIT 编译效果:查看是否有过多方法被解释执行,可能需要调整 JIT 编译策略。
  6. 注意事项

    • jstat 主要用于监控和诊断 JVM 性能,但它不提供详细的线程或堆栈信息。如果需要更深入的分析,可以结合 jstackjmap 或 VisualVM 等工具。
    • jstat 的命令可以按时间间隔持续输出,适合用于实时监控。
    • 需要确保你有足够的权限访问目标 JVM 进程(通常需要是目标进程的所有者或具有管理员权限)。

MAT

Eclipse Memory Analyzer Tool(MAT)是一个强大的工具,用于分析 Java 应用程序中的堆转储(heap dump),帮助开发者诊断内存泄漏和内存使用不当的问题。以下是使用 MAT 工具的基本步骤:

1. 下载并安装 MAT

首先,你需要下载并安装 Eclipse Memory Analyzer Tool(MAT):

  • 访问 MAT 官网 下载适用于你操作系统的版本。
  • 解压并运行 MAT。

2. 获取堆转储文件

MAT 的主要功能是分析堆转储文件。堆转储(heap dump)是 JVM 在运行过程中产生的内存快照,它包含了堆内存中所有对象的详细信息。你可以通过以下几种方式获得堆转储文件:

2.1 通过 JDK 工具生成堆转储文件

  • 使用 jmap 命令:这是最常用的方法之一。你可以通过 jmap 命令来生成堆转储文件。

    jmap -dump:live,format=b,file=heapdump.hprof <PID>
    

    其中:

    • -dump:指定堆转储的生成方式。
    • live:表示只包含活动对象。
    • format=b:表示输出文件格式为二进制格式(可以是 .hprof 格式)。
    • <PID>:目标 Java 进程的进程 ID。

    例如,生成堆转储文件 heapdump.hprof

2.2 通过 JVM 参数生成堆转储文件

你也可以在 JVM 启动时通过以下参数来设置自动生成堆转储文件:

-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=heapdump.hprof

这样,在发生 OutOfMemoryError 时,JVM 会自动生成堆转储文件。

3. 导入堆转储文件到 MAT

  1. 打开 MAT 工具。
  2. 选择 File -> Open Heap Dump
  3. 选择你之前生成的 .hprof 文件,并点击 Open

4. 分析堆转储文件

当堆转储文件加载完毕后,MAT 会开始分析堆转储中的内容。分析过程中,MAT 会为你提供各种视图和统计信息,帮助你识别内存问题。

4.1 初步分析

MAT 会在打开堆转储文件后自动生成一个快速概览报告。你可以在报告中查看以下信息:

  • 对象数量统计:显示堆中每种类型对象的数量和占用内存。
  • 最常用的类:列出内存中占用最多空间的类。
  • 内存泄漏提示:MAT 会尝试自动检测潜在的内存泄漏(如果某个对象占用了大量内存且没有被正确释放)。

4.2 查看对象实例

在 MAT 中,你可以查看堆中的所有对象实例。选择 Dominator Tree 视图或 Histogram 视图可以帮助你识别占用大量内存的对象。

  • Dominator Tree:显示对象之间的引用关系,能够帮助你查找大对象及其依赖的对象。
  • Histogram:显示对象类型和实例的分布,你可以按对象的实例数或占用的内存量排序。

4.3 查找内存泄漏

MAT 提供了一个强大的内存泄漏检测工具:

  • 点击 Leak Suspects Report 按钮,这将启动 MAT 的内存泄漏检查功能。MAT 会根据堆的引用图谱分析是否有无法回收的对象。
  • 分析结果将列出可能的内存泄漏源,并显示这些对象的详细信息,如大小、引用路径等。

4.4 对象路径分析

你可以使用 Path to GC Roots 功能来追踪某个对象为何没有被垃圾回收。MAT 会显示从该对象到垃圾回收根节点(GC Root)之间的引用路径,这有助于发现那些导致对象无法被回收的引用。

5. 分析常见问题

MAT 可以帮助你诊断一些常见的内存问题:

  • 内存泄漏:MAT 会显示无法回收的对象及其引用路径,帮助你找出内存泄漏的根源。
  • 高内存使用:MAT 会显示占用大量内存的对象和类,有助于你识别内存使用不当的地方。
  • 对象增长异常:通过跟踪对象实例的增长趋势,你可以发现哪些对象的增长异常,导致内存不断增加。

6. 生成报告

完成分析后,你可以生成详细的报告。MAT 支持导出为各种格式,如 HTML、XML 等。可以通过 File -> Export 来导出分析结果。

7. 优化建议

根据 MAT 分析结果,你可能会发现以下几类问题:

  • 不可达对象:这些对象已经没有活跃的引用,但依然占用内存。
  • 过大的单一对象:某些单个对象的内存占用可能过高,建议优化其存储结构或拆分成更小的对象。
  • 不必要的引用:某些对象的引用可能不必要,导致它们无法被垃圾回收。

通过这些信息,你可以着手优化代码,消除内存泄漏和过度内存使用的情况。

8. 常见的分析视图

  • Dominator Tree:按内存占用的对象层次结构展示堆中的对象,可以识别哪些对象是内存的“支配者”。
  • Histogram:显示堆中所有对象的统计信息,按类、大小等排序。
  • Leak Suspects Report:自动生成的内存泄漏分析报告。
  • Path to GC Roots:帮助分析某个对象为何无法被垃圾回收。

Jconsole

JConsole 是 JDK 自带的一个用于监视和管理 Java 应用程序的图形化工具。它可以实时显示 JVM 的运行状况,包括内存使用、线程活动、垃圾回收、类加载等信息,适合开发者进行性能监控和故障诊断。以下是使用 JConsole 的基本步骤:

1. 启动 JConsole

1.1 在命令行启动

  • 确保 JDK 已安装,并将 JDK 的 bin 目录加入到系统的环境变量 PATH 中。

  • 打开命令行终端,输入以下命令启动 JConsole:

    jconsole
    

    这会打开 JConsole 图形界面。

1.2 通过 Java 应用程序启动

你也可以通过直接启动 Java 应用程序时开启远程监控来启动 JConsole。

  • 例如,在启动 Java 应用时加上 JVM 参数:

    java -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=12345 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -jar your-application.jar
    

    这将启用 JMX 远程监控,并使得你能够通过 JConsole 连接到正在运行的应用程序。

2. 连接到 Java 应用

启动 JConsole 后,它会列出当前所有正在运行的 Java 进程。你可以选择以下方式连接到你想监控的 Java 应用程序:

2.1 本地连接

如果你是在本地机器上运行 Java 程序,JConsole 会自动列出当前所有的 Java 进程。你只需选择你要连接的进程并点击 Connect 即可。

2.2 远程连接

如果你想连接到远程的 Java 应用程序,选择 Remote Process 选项,并输入远程应用程序的主机名和端口号(例如:hostname:12345)。确保目标应用程序已经启用 JMX 远程连接。

3. 使用 JConsole 监控应用程序

成功连接后,JConsole 会显示多个监控标签页,分别用于展示不同的系统和应用状态信息。以下是一些主要的功能标签:

3.1 Overview(概览)

  • CPU 使用情况:显示 JVM 进程的 CPU 使用率。
  • 内存使用情况:显示 JVM 堆内存的使用情况,包括年轻代、老年代和永久代(如果有的话)的内存使用。
  • 线程活动:显示当前活动线程数以及线程状态的分布。

3.2 Memory(内存)

该标签页提供堆内存的详细信息,包括:

  • 堆内存:显示当前堆的使用情况,按年轻代、老年代、持久代划分。
  • 内存池:显示不同内存池(如 Eden 区、Survivor 区、Old 区)的内存使用情况。
  • 垃圾回收:显示垃圾回收的次数和时间。

在这里,你还可以手动触发垃圾回收(点击 Perform GC 按钮)。

3.3 Threads(线程)

该标签页显示 JVM 中的线程活动,包括:

  • 线程概览:显示当前线程的总数和线程状态(如运行中、阻塞中、等待中等)。
  • 线程堆栈:你可以查看每个线程的堆栈跟踪,帮助你诊断死锁等线程问题。

3.4 Classes(类)

显示 JVM 中加载的类的统计信息,包括:

  • 加载的类数:显示当前加载的类数量。
  • 加载/卸载类:显示加载和卸载类的数量,帮助你检测是否有类加载异常。

3.5 VM (虚拟机)

该标签提供 JVM 进程的状态和配置,包括:

  • JVM 参数:显示当前 JVM 启动时使用的参数。
  • 系统属性:显示系统属性列表。

3.6 MBeans(MBeans)

在这个标签页中,你可以查看和操作应用程序暴露的 JMX MBeans。MBeans 是 Java 管理扩展 (JMX) 中用于管理应用程序、设备、系统或网络服务的组件。如果你有自定义的 MBeans(例如应用程序监控数据),可以在这里进行交互。

4. 性能优化和问题诊断

使用 JConsole 监控时,开发者可以发现以下性能瓶颈并进行优化:

  • 内存泄漏:如果堆内存使用不断上升,而垃圾回收没有有效清除对象,可能是内存泄漏的征兆。你可以通过 Memory 视图中的堆内存使用情况进行检查。

  • 高 CPU 使用率:通过 Overview 标签中的 CPU 使用图表,检查应用程序是否出现异常的 CPU 消耗,进而优化相关的代码或调整 JVM 参数。

  • 线程问题:通过 Threads 视图,你可以查看线程的活跃度,检查是否存在线程阻塞、死锁等问题。

  • 垃圾回收瓶颈:通过 Memory 标签,你可以监控垃圾回收的频率和时间,过长的垃圾回收时间可能是性能瓶颈的标志,可以考虑调优堆大小或使用其他垃圾回收器(如 G1 GC)。

5. 警告和告警

JConsole 本身并不提供告警功能,但是可以通过监控 JVM 的各种性能指标并结合日志分析来触发告警。例如,当垃圾回收频繁且停顿时间过长时,你可以通过配置合适的告警系统来响应这些问题。

总结

JConsole 是一个轻量级且功能丰富的监控工具,适用于开发者实时监控 Java 应用的运行状态。通过 JConsole,可以直观地看到 Java 应用的内存使用、线程状态、垃圾回收等关键指标,及时发现和解决性能问题。

VisualVM

VisualVM 是一个功能强大的 Java 虚拟机(JVM)监控、性能分析和故障排查工具,允许开发者实时查看 JVM 的运行情况,进行性能分析、内存分析、线程分析等。VisualVM 是 JDK 自带的工具,可以帮助开发者在运行时获取 Java 程序的详细信息,从而进行优化和问题诊断。

以下是 VisualVM 使用的步骤:

1. 安装 VisualVM

  • VisualVM 在 JDK 8 及以上版本中已经作为 JDK 工具之一预装。你可以直接在 JDK 的 bin 目录中找到 jvisualvm 可执行文件。
  • 如果你使用的是较旧的 JDK 或者想安装 VisualVM 最新版本,可以访问 VisualVM 官网 下载并安装。

2. 启动 VisualVM

2.1 从命令行启动

  • 在命令行中直接输入 jvisualvm,如果已经安装并配置好 JDK 环境变量,VisualVM 会自动启动。

2.2 从 JDK bin 目录启动

  • 如果 jvisualvm 没有配置在 PATH 环境变量中,可以直接在 JDK 的 bin 目录下找到并运行 jvisualvm

2.3 启动后的界面

  • 启动 VisualVM 后,你会看到一个包含多个选项卡的界面,主要包括:
    • Applications:列出当前运行的本地和远程 Java 应用程序。
    • ProfilerMonitorHeap Dump 等标签,用于查看和分析 Java 应用的各类性能指标。

3. 连接到 Java 应用程序

VisualVM 支持连接本地和远程的 Java 应用程序,具体方式如下:

3.1 本地连接

  • 启动 VisualVM 后,Applications 标签页下会自动显示本地机器上所有正在运行的 Java 进程。
  • 选择你要监控的进程,双击即可连接。

3.2 远程连接

  • 如果你希望监控远程机器上的 Java 应用程序,需要在远程 JVM 中启用 JMX 远程连接:
    • 在启动 Java 应用时,使用以下 JVM 参数来启用远程监控:

      java -Dcom.sun.management.jmxremote \
           -Dcom.sun.management.jmxremote.port=12345 \
           -Dcom.sun.management.jmxremote.ssl=false \
           -Dcom.sun.management.jmxremote.authenticate=false \
           -jar your-application.jar
      
    • 然后,在 VisualVM 中,右键点击 Applications 标签页的空白区域,选择 Add Remote Host

    • 输入远程主机的 IP 地址,并添加远程 JVM 连接信息(如 hostname:port),连接后可以查看远程应用程序的性能信息。

4. 使用 VisualVM 监控应用程序

4.1 Monitor(监控)

  • Monitor 标签页展示了应用程序的实时运行状态,包括:
    • CPU 使用情况:展示应用程序的 CPU 占用情况。
    • 内存使用情况:显示应用程序堆内存和非堆内存的使用情况。
    • 垃圾回收:显示垃圾回收的情况和时间。
    • 线程活动:显示线程的活动状态,帮助你查看线程的使用情况。

4.2 Profiler(性能分析)

  • Profiler 标签页提供详细的性能分析,包括:
    • CPU 性能分析:通过采样方式,查看哪些方法在 CPU 上消耗最多的时间。
    • 内存性能分析:查看对象分配和内存使用的情况,帮助检测内存泄漏。
    • 方法调用图:展示哪些方法最耗时,或者哪个方法被调用最多。

4.3 Heap Dump(堆转储)

  • Heap Dump 允许你生成堆转储文件,并分析对象的内存占用情况。它可以帮助你发现内存泄漏,查看哪些对象占用的内存较多。
    • Heap Dump 标签页中,可以通过点击 Heap Dump 按钮生成堆转储。
    • 在生成堆转储后,VisualVM 会展示堆中各个对象的详细信息,包括类名、实例数和内存占用等。

4.4 Thread Dump(线程转储)

  • Thread Dump 用于查看当前 JVM 中所有线程的状态,以及线程的堆栈信息。
    • Threads 标签页中,你可以查看当前线程的状态(如运行中、等待中、阻塞中等),以及线程的堆栈信息。
    • 通过 Thread Dump,你可以帮助诊断死锁、线程阻塞等问题。

4.5 VM Options(虚拟机选项)

  • VM Options 中,可以查看和修改 JVM 启动时的参数配置。
  • 如果你发现某些性能问题,需要调优 JVM 参数,可以通过这个界面直接调整。

5. 诊断和性能优化

5.1 内存泄漏检测

通过 ProfilerHeap Dump,你可以检测内存泄漏。内存泄漏通常表现为堆内存使用持续上升,且垃圾回收无法释放内存。你可以通过以下方式诊断:

  • Profiler 中查看对象的分配情况,查找是否有大量对象未被回收。
  • Heap Dump 中查看哪些对象占用了大量内存,确定可能的内存泄漏源。

5.2 CPU 使用分析

通过 Profiler 中的 CPU Sampling,你可以查看哪些方法消耗了过多的 CPU 时间,进而进行性能优化。

  • 分析耗时方法,查看代码中是否存在性能瓶颈。
  • 优化算法或逻辑,减少 CPU 占用。

5.3 线程分析

通过 ThreadsThread Dump,你可以诊断线程的问题,例如死锁、线程饥饿等。

  • 检查线程的状态,看看是否存在大量阻塞或等待的线程。
  • 使用 Thread Dump 分析线程堆栈,查看是否有死锁发生。

6. 生成报告

VisualVM 提供了将分析结果导出为报告的功能。你可以导出 Heap DumpThread Dump,并生成 性能分析报告。这些报告可以帮助你保存诊断结果,并与团队成员分享。

总结

VisualVM 是一个非常强大的 Java 性能监控和故障诊断工具,具有实时监控、性能分析、内存分析、线程分析等功能。通过使用 VisualVM,开发者能够及时发现性能瓶颈,优化应用程序,解决内存泄漏、死锁等问题,从而提升 Java 应用程序的稳定性和性能。

Arthus

Arthas 是一个开源的 Java 诊断工具,专为 Java 程序提供动态诊断功能,能够在不修改代码的情况下实时诊断、分析和优化应用程序。它支持查看堆栈、调试线程、监控 JMX 等功能,非常适用于生产环境中的问题排查。

以下是 Arthas 的基本使用步骤:

1. 安装和准备

Arthas 是通过命令行工具运行的,可以通过以下几种方式安装和启动:

1.1 使用 JAR 包 直接运行

  1. Arthas GitHub官方网站 下载最新版本的 Arthas JAR 包。

  2. 使用以下命令启动 Arthas:

    java -jar arthas-boot.jar
    

    运行后,Arthas 会尝试连接到当前机器上所有的 Java 进程。

1.2 使用 Homebrew 安装(macOS/Linux)

  • 在 macOS 或 Linux 系统上,你可以通过 Homebrew 安装 Arthas:

    brew install arthas
    

1.3 使用 Docker 启动

如果你使用 Docker,可以直接通过 Docker 启动 Arthas:

docker run -it --rm -v /tmp:/tmp --pid=host  aliyun/arthas

2. 连接到 Java 进程

启动 Arthas 后,它会列出当前运行在本地的所有 Java 进程。你需要选择你想要调试或诊断的进程。

  • 输入相应的进程 ID(PID),然后按回车连接该进程。

3. 常用命令

Arthas 提供了丰富的命令行工具,以下是一些常用的命令:

3.1 monitor — 方法监控

monitor 用于监控某个方法的调用次数、耗时等信息。比如,监控 com.example.MyClass 类的 myMethod 方法:

monitor com.example.MyClass myMethod

可以增加 -n 参数指定显示多少次调用统计,-d 参数指定显示方法耗时等信息。

3.2 jad — 反编译

jad 用于反编译类的字节码,查看该类的源码。比如反编译 com.example.MyClass

jad com.example.MyClass

反编译后,Arthas 会显示该类的 Java 源代码。

3.3 stack — 查看线程栈

stack 命令用来查看当前 JVM 中所有线程的堆栈信息,非常适合排查死锁、线程阻塞等问题。默认查看所有线程的堆栈信息,输入以下命令:

stack

可以使用 -t 参数查看特定线程的堆栈:

stack -t <thread-name>

3.4 thread — 线程监控

thread 命令提供线程状态的实时监控,可以查看线程池中的线程数量、线程状态等信息:

thread

3.5 watch — 监视方法调用

watch 可以在不修改代码的情况下动态地插桩某个方法,并打印方法执行的入参、返回值或执行时间等。例如,监控 com.example.MyClass 中的 myMethod 方法,并打印入参和返回值:

watch com.example.MyClass myMethod '{params,returnObj}'

如果你只想监控方法的执行时间,可以使用如下命令:

watch com.example.MyClass myMethod -t

3.6 trace — 方法调用追踪

trace 可以用来追踪某个方法的执行情况,包括方法的调用栈、耗时等。比如:

trace com.example.MyClass myMethod

3.7 cls — 清除命令

当命令行输出太多时,你可以使用 cls 来清除屏幕内容,保持终端干净:

cls

3.8 exit — 退出 Arthas

如果你完成了对进程的诊断,可以通过 exit 命令退出 Arthas:

exit

4. 调试和分析

4.1 查看 JVM 信息

可以使用 jvm 命令查看 JVM 的相关信息,包括堆内存、非堆内存、线程数、垃圾回收等:

jvm

4.2 查看类加载器信息

可以使用 classloader 命令查看当前 JVM 的类加载器信息:

classloader

4.3 动态修改类

Arthas 还可以动态修改类,热更新方法体(使用 bytecode 命令)。例如,修改某个类的字节码:

bytecode com.example.MyClass

然后选择操作,如修改、替换等。可以直接在生产环境进行调试,不需要重启应用。

5. 高级功能

Arthas 支持一些更高级的功能,比如:

5.1 heapdump — 堆转储

通过 heapdump 命令,你可以生成堆转储文件并分析内存使用情况。该命令会生成一个堆转储文件并保存到指定位置:

heapdump

5.2 sc — 查看 Spring Bean

如果你的应用是基于 Spring 的,可以使用 sc 命令来查看 Spring 上下文中的 Bean 信息。比如查看某个 Bean:

sc com.example.MyService

5.3 watchtrace 的条件断点

watchtrace 命令支持设置条件断点(如方法执行时间超过一定阈值时触发)。例如,在 myMethod 方法上设置一个执行时间超过 100ms 时触发的 watch 命令:

watch com.example.MyClass myMethod 'returnObj' -n 10 -t -x 100

6. 导出诊断数据

如果需要将 Arthas 的诊断结果保存为文件或共享给团队成员,可以使用 log 命令导出日志:

log /tmp/arthas.log

7. 退出 Arthas

完成诊断后,使用 exit 命令退出 Arthas:

exit