JMAP:
jmap
是 Java 提供的一个工具,用于生成 Java 堆内存的快照,并帮助分析堆的使用情况。它常用于诊断 Java 应用程序中的内存问题,如内存泄漏或性能问题。
jmap
常用步骤
-
查看所有 Java 进程
使用
jmap
前,首先可以查看当前机器上所有运行的 Java 进程,获取目标进程的 PID(进程ID)。bashjps
该命令会列出当前系统中所有运行的 Java 进程及其进程 ID。例如:
bash12345 MyJavaApp
这里
12345
是进程 ID。 -
生成堆转储(Heap Dump)
使用
jmap
生成堆转储文件(heap dump),这是分析堆内存使用情况的重要工具。bashjmap -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 等)进一步分析。 -
查看堆内存使用情况
可以使用
jmap
查看堆内存的基本使用情况,比如查看堆的总大小、各个区域的大小、内存使用情况等。bashjmap -heap <PID>
输出示例:
iniHeap 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)
该命令显示堆内存的配置和使用情况,例如年轻代、老年代、元空间的大小等。
-
查看堆中对象的详细信息
使用
jmap -histo
可以查看堆中类的实例数量和内存占用。bashjmap -histo <PID>
输出会列出堆内所有类的实例和占用的内存。例如:
yamlnum #instances #bytes class name ---------------------------------------------- 1: 9876 1556789 [C 2: 12345 9876543 java.lang.String 3: 4321 1234567 java.util.ArrayList ...
这有助于查找占用大量内存的类和对象。
-
查看类的详细内存使用情况
使用
jmap -F
可以强制执行一些操作,例如强制进行堆转储或强制查看堆内存。bashjmap -F -heap <PID>
该命令在分析堆使用情况时可能有所帮助。
注意事项
- 权限问题 :通常需要以管理员权限运行
jmap
,或者确保当前用户有足够的权限访问目标 Java 进程的内存。 - 性能开销:生成堆转储或频繁查看堆内存会引入额外的性能开销,因此在生产环境中使用时应小心。
- JVM参数 :某些 JVM 参数(例如
-XX:+HeapDumpOnOutOfMemoryError
)也能帮助在发生内存溢出时自动生成堆转储文件。
JSRACK
jstack
是 Java 提供的一个工具,用于生成 Java 应用程序的线程堆栈(Thread Dump)。它可以帮助你查看线程的执行状态,诊断死锁、线程挂起或性能问题等。
jstack
常用步骤
-
查看 Java 进程
在使用
jstack
之前,首先需要查看当前机器上所有正在运行的 Java 进程,获取目标进程的 PID(进程 ID)。可以使用jps
命令列出所有 Java 进程。bashjps
该命令会列出当前系统中所有运行的 Java 进程及其进程 ID。例如:
bash12345 MyJavaApp
这里
12345
是 Java 应用程序的进程 ID(PID)。 -
生成线程堆栈(Thread Dump)
使用
jstack
命令可以生成 Java 应用程序的线程堆栈信息。bashjstack <PID>
<PID>
:替换为目标 Java 进程的进程 ID。
该命令会输出所有线程的堆栈信息,包括每个线程的当前状态、正在执行的方法等。
输出示例:
bash"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)
该输出显示了线程的状态、调用栈以及锁的状态等信息。
-
将线程堆栈输出保存到文件
如果堆栈信息较长,你可以将其输出保存到文件中,便于进一步分析。
bashjstack <PID> > threaddump.txt
这样线程堆栈信息就会被保存到
threaddump.txt
文件中,之后可以用文本编辑器查看或分析。 -
生成死锁(Deadlock)信息
jstack
还可以用来检查死锁。死锁发生时,两个或多个线程互相等待对方释放资源,导致程序无法继续执行。使用-l
选项可以显示死锁信息。bashjstack -l <PID>
如果存在死锁,输出将包括死锁相关的信息,像下面这样:
bashFound 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)
输出中列出了参与死锁的线程,以及它们当前的堆栈信息。你可以根据这些信息来修复死锁问题。
-
分析线程堆栈信息
生成线程堆栈后,分析堆栈信息非常重要。你需要检查每个线程的状态、调用栈,以及是否存在死锁或长时间运行的线程。以下是一些关键点:
- 线程状态 :检查线程是否处于
WAITING
、TIMED_WAITING
、BLOCKED
或RUNNABLE
状态。 - 死锁:如果多个线程在互相等待对方释放锁,则可能存在死锁。
- CPU占用高:某些线程可能在耗费大量 CPU,长时间运行在同一个方法里。
- 线程状态 :检查线程是否处于
-
分析线程状态
线程堆栈的状态可以有以下几种:
NEW
: 新创建的线程,尚未开始执行。RUNNABLE
: 线程正在执行(包括等待 CPU 时间)。BLOCKED
: 线程正在等待获取一个锁。WAITING
: 线程在等待某个条件发生。TIMED_WAITING
: 线程在等待一个特定时间后会自动唤醒。TERMINATED
: 线程已经结束执行。
通过分析这些状态,可以帮助诊断应用程序的性能问题。
注意事项
- 权限问题 :你通常需要管理员权限或目标进程的用户权限才能使用
jstack
生成线程堆栈信息。 - 生产环境使用小心:在生产环境中,生成线程堆栈会对应用程序的性能造成一定的影响,尤其是在高负载的情况下,因此使用时要小心。
- 堆栈信息量大:线程堆栈信息可能非常庞大,分析时需要耐心。
Jstat
jstat
是 Java 提供的一个命令行工具,用于监控和分析 Java 虚拟机(JVM)的运行时统计信息。通过 jstat
,你可以查看 JVM 各种性能指标,例如内存使用、垃圾回收、类加载、编译等。这对于性能调优和故障排查非常有帮助。
jstat
使用步骤
-
查看 JVM 进程的 PID
在使用
jstat
之前,首先需要找出目标 JVM 进程的进程 ID(PID)。你可以通过jps
命令来列出系统中所有的 Java 进程。bashjps
该命令会列出当前系统上运行的所有 Java 进程。例如:
bash12345 MyJavaApp
这里
12345
就是 Java 应用程序的进程 ID(PID)。 -
查看
jstat
支持的选项jstat
命令有多个选项,可以用于查看不同的 JVM 统计信息。你可以通过-help
参数来查看支持的选项和用法。bashjstat -help
输出将列出所有可用的选项,例如:
-gc
:显示垃圾回收信息。-gcutil
:显示垃圾回收的统计信息(百分比形式)。-class
:显示类加载信息。-compiler
:显示 JIT 编译器信息。
-
使用
jstat
命令查看 JVM 性能指标下面是一些常用的
jstat
命令示例。-
查看垃圾回收(GC)统计信息
-gc
选项显示垃圾回收的详细信息,常用来检查堆内存使用情况。bashjstat -gc <PID> 1000
其中:
<PID>
是目标 Java 进程的 PID。1000
是时间间隔(单位:毫秒),表示每 1000 毫秒打印一次 GC 信息。
输出示例:
yamlS0C 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
每列的含义如下:
S0C
和S1C
: Survivor 区域的容量。S0U
和S1U
: Survivor 区域的已使用内存。EC
和EU
: Eden 区域的容量和已使用内存。OC
和OU
: Old 区域的容量和已使用内存。MC
和MU
: Metaspace 区域的容量和已使用内存。CCSC
和CCSU
:压缩类空间的容量和已使用内存。YGC
和YGCT
:年轻代垃圾回收次数和时间。FGC
和FGCT
:老年代垃圾回收次数和时间。GCT
:总垃圾回收时间。
-
查看类加载信息
-class
选项显示类加载器的相关信息。bashjstat -class <PID>
输出示例:
cssLoaded Unloaded Time 2345 12 45.23
Loaded
:加载的类数量。Unloaded
:卸载的类数量。Time
:类加载时间。
-
查看 JIT 编译器信息
-compiler
选项显示 JIT 编译器的信息,主要用来查看方法的编译情况。bashjstat -compiler <PID>
输出示例:
yaml2345 12 45.23
-
查看 Java 堆内存使用情况
-gcutil
选项显示 JVM 堆内存的使用情况,通常用于监控垃圾回收的效果。bashjstat -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
各列代表:
S0
、S1
:分别是 survivor 区的使用百分比。E
:Eden 区的使用百分比。O
:Old 区的使用百分比。M
:Metaspace 区的使用百分比。CCS
:压缩类空间的使用百分比。YGC
、YGCT
:年轻代垃圾回收次数和时间。FGC
、FGCT
:老年代垃圾回收次数和时间。GCT
:总垃圾回收时间。
-
-
常用选项总结
以下是
jstat
的一些常用选项:-gc
:显示垃圾回收信息。-gcutil
:以百分比显示垃圾回收的统计信息。-class
:显示类加载信息。-compiler
:显示 JIT 编译器信息。-printcompilation
:显示已编译的代码。
-
分析
jstat
输出信息jstat
输出的统计数据可以帮助你了解 JVM 的内存使用情况,尤其是垃圾回收的行为。根据输出数据,你可以判断:- GC 是否频繁:频繁的 GC 可能表明堆内存不足或者对象创建过于频繁。
- 内存是否有泄漏:长期不回收的内存可能是内存泄漏的征兆。
- JIT 编译效果:查看是否有过多方法被解释执行,可能需要调整 JIT 编译策略。
-
注意事项
jstat
主要用于监控和诊断 JVM 性能,但它不提供详细的线程或堆栈信息。如果需要更深入的分析,可以结合jstack
、jmap
或 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
命令来生成堆转储文件。bashjmap -dump:live,format=b,file=heapdump.hprof <PID>
其中:
-dump
:指定堆转储的生成方式。live
:表示只包含活动对象。format=b
:表示输出文件格式为二进制格式(可以是.hprof
格式)。<PID>
:目标 Java 进程的进程 ID。
例如,生成堆转储文件
heapdump.hprof
。
2.2 通过 JVM 参数生成堆转储文件
你也可以在 JVM 启动时通过以下参数来设置自动生成堆转储文件:
bash
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=heapdump.hprof
这样,在发生 OutOfMemoryError
时,JVM 会自动生成堆转储文件。
3. 导入堆转储文件到 MAT
- 打开 MAT 工具。
- 选择 File -> Open Heap Dump。
- 选择你之前生成的
.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:
bashjconsole
这会打开 JConsole 图形界面。
1.2 通过 Java 应用程序启动
你也可以通过直接启动 Java 应用程序时开启远程监控来启动 JConsole。
-
例如,在启动 Java 应用时加上 JVM 参数:
bashjava -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 应用程序。
- Profiler 、Monitor 、Heap Dump 等标签,用于查看和分析 Java 应用的各类性能指标。
3. 连接到 Java 应用程序
VisualVM 支持连接本地和远程的 Java 应用程序,具体方式如下:
3.1 本地连接
- 启动 VisualVM 后,
Applications
标签页下会自动显示本地机器上所有正在运行的 Java 进程。 - 选择你要监控的进程,双击即可连接。
3.2 远程连接
- 如果你希望监控远程机器上的 Java 应用程序,需要在远程 JVM 中启用 JMX 远程连接:
-
在启动 Java 应用时,使用以下 JVM 参数来启用远程监控:
bashjava -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 内存泄漏检测
通过 Profiler 和 Heap Dump,你可以检测内存泄漏。内存泄漏通常表现为堆内存使用持续上升,且垃圾回收无法释放内存。你可以通过以下方式诊断:
- 在 Profiler 中查看对象的分配情况,查找是否有大量对象未被回收。
- 在 Heap Dump 中查看哪些对象占用了大量内存,确定可能的内存泄漏源。
5.2 CPU 使用分析
通过 Profiler 中的 CPU Sampling,你可以查看哪些方法消耗了过多的 CPU 时间,进而进行性能优化。
- 分析耗时方法,查看代码中是否存在性能瓶颈。
- 优化算法或逻辑,减少 CPU 占用。
5.3 线程分析
通过 Threads 和 Thread Dump,你可以诊断线程的问题,例如死锁、线程饥饿等。
- 检查线程的状态,看看是否存在大量阻塞或等待的线程。
- 使用 Thread Dump 分析线程堆栈,查看是否有死锁发生。
6. 生成报告
VisualVM 提供了将分析结果导出为报告的功能。你可以导出 Heap Dump 或 Thread Dump ,并生成 性能分析报告。这些报告可以帮助你保存诊断结果,并与团队成员分享。
总结
VisualVM 是一个非常强大的 Java 性能监控和故障诊断工具,具有实时监控、性能分析、内存分析、线程分析等功能。通过使用 VisualVM,开发者能够及时发现性能瓶颈,优化应用程序,解决内存泄漏、死锁等问题,从而提升 Java 应用程序的稳定性和性能。
Arthus
Arthas 是一个开源的 Java 诊断工具,专为 Java 程序提供动态诊断功能,能够在不修改代码的情况下实时诊断、分析和优化应用程序。它支持查看堆栈、调试线程、监控 JMX 等功能,非常适用于生产环境中的问题排查。
以下是 Arthas 的基本使用步骤:
1. 安装和准备
Arthas 是通过命令行工具运行的,可以通过以下几种方式安装和启动:
1.1 使用 JAR 包 直接运行
-
从 Arthas GitHub 或 官方网站 下载最新版本的 Arthas JAR 包。
-
使用以下命令启动 Arthas:
bashjava -jar arthas-boot.jar
运行后,Arthas 会尝试连接到当前机器上所有的 Java 进程。
1.2 使用 Homebrew 安装(macOS/Linux)
-
在 macOS 或 Linux 系统上,你可以通过 Homebrew 安装 Arthas:
bashbrew install arthas
1.3 使用 Docker 启动
如果你使用 Docker,可以直接通过 Docker 启动 Arthas:
bash
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
方法:
bash
monitor com.example.MyClass myMethod
可以增加 -n
参数指定显示多少次调用统计,-d
参数指定显示方法耗时等信息。
3.2 jad
--- 反编译
jad
用于反编译类的字节码,查看该类的源码。比如反编译 com.example.MyClass
:
bash
jad com.example.MyClass
反编译后,Arthas 会显示该类的 Java 源代码。
3.3 stack
--- 查看线程栈
stack
命令用来查看当前 JVM 中所有线程的堆栈信息,非常适合排查死锁、线程阻塞等问题。默认查看所有线程的堆栈信息,输入以下命令:
bash
stack
可以使用 -t
参数查看特定线程的堆栈:
bash
stack -t <thread-name>
3.4 thread
--- 线程监控
thread
命令提供线程状态的实时监控,可以查看线程池中的线程数量、线程状态等信息:
bash
thread
3.5 watch
--- 监视方法调用
watch
可以在不修改代码的情况下动态地插桩某个方法,并打印方法执行的入参、返回值或执行时间等。例如,监控 com.example.MyClass
中的 myMethod
方法,并打印入参和返回值:
bash
watch com.example.MyClass myMethod '{params,returnObj}'
如果你只想监控方法的执行时间,可以使用如下命令:
bash
watch com.example.MyClass myMethod -t
3.6 trace
--- 方法调用追踪
trace
可以用来追踪某个方法的执行情况,包括方法的调用栈、耗时等。比如:
bash
trace com.example.MyClass myMethod
3.7 cls
--- 清除命令
当命令行输出太多时,你可以使用 cls
来清除屏幕内容,保持终端干净:
bash
cls
3.8 exit
--- 退出 Arthas
如果你完成了对进程的诊断,可以通过 exit
命令退出 Arthas:
bash
exit
4. 调试和分析
4.1 查看 JVM 信息
可以使用 jvm
命令查看 JVM 的相关信息,包括堆内存、非堆内存、线程数、垃圾回收等:
bash
jvm
4.2 查看类加载器信息
可以使用 classloader
命令查看当前 JVM 的类加载器信息:
bash
classloader
4.3 动态修改类
Arthas 还可以动态修改类,热更新方法体(使用 bytecode
命令)。例如,修改某个类的字节码:
bash
bytecode com.example.MyClass
然后选择操作,如修改、替换等。可以直接在生产环境进行调试,不需要重启应用。
5. 高级功能
Arthas 支持一些更高级的功能,比如:
5.1 heapdump
--- 堆转储
通过 heapdump
命令,你可以生成堆转储文件并分析内存使用情况。该命令会生成一个堆转储文件并保存到指定位置:
bash
heapdump
5.2 sc
--- 查看 Spring Bean
如果你的应用是基于 Spring 的,可以使用 sc
命令来查看 Spring 上下文中的 Bean 信息。比如查看某个 Bean:
bash
sc com.example.MyService
5.3 watch
和 trace
的条件断点
watch
和 trace
命令支持设置条件断点(如方法执行时间超过一定阈值时触发)。例如,在 myMethod
方法上设置一个执行时间超过 100ms 时触发的 watch
命令:
bash
watch com.example.MyClass myMethod 'returnObj' -n 10 -t -x 100
6. 导出诊断数据
如果需要将 Arthas 的诊断结果保存为文件或共享给团队成员,可以使用 log
命令导出日志:
bash
log /tmp/arthas.log
7. 退出 Arthas
完成诊断后,使用 exit
命令退出 Arthas:
bash
exit