JVM调优 jstat 与 jstack
jstat
jstat
是一个命令行工具,用于监控正在运行的 Java 虚拟机(JVM)的性能。它能够显示关于堆内存、非堆内存、类加载、编译器活动、垃圾收集器(GC)活动等各种运行时数据的信息。jstat
是 JDK 自带的工具之一,无需额外安装。
要使用 jstat
监控 JVM 的内存和 GC 情况,你可以按照以下步骤操作:
启动 JVM
首先,你需要启动一个 Java 应用程序,确保你知道该应用程序的进程 ID(PID)。你可以通过 jps
命令找到正在运行的 Java 进程。
使用 jstat
基本语法
jstat [option] [interval] [vmid]
option
:指定要收集哪种类型的数据。interval
:采样间隔(毫秒),如果省略则只输出一次。vmid
:虚拟机的进程 ID。
常用选项
-gc
:显示有关垃圾收集的统计信息。-gccapacity
:显示堆和非堆内存容量信息。-gcutil
:显示垃圾收集的百分比利用率。-class
:显示类加载统计信息。-compiler
:显示编译器统计信息。
示例
-
查看 JVM 的 GC 统计信息:
jstat -gc 12345
其中
12345
是你的 Java 进程的 PID。 -
定时查看 GC 统计信息,每 1 秒钟一次:
jstat -gc 1000 12345
-
查看堆内存和 GC 利用率:
jstat -gcutil 12345
输出解释
当你使用 -gc
或 -gcutil
等选项时,jstat
将输出一列数据,每一列代表了 JVM 的不同部分或活动。例如:
S0C
和S1C
:表示幸存者空间 0 和幸存者空间 1 的容量。S0U
和S1U
:表示幸存者空间 0 和幸存者空间 1 的使用量。EC
:表示 Eden 区的容量。EU
:表示 Eden 区的使用量。OC
:表示老年代的容量。OU
:表示老年代的使用量。MC
:表示元空间的容量(在 JDK 9 及更高版本中)。MU
:表示元空间的使用量(在 JDK 9 及更高版本中)。CCSC
:表示压缩类空间的容量(在 JDK 9 及更高版本中)。CCSU
:表示压缩类空间的使用量(在 JDK 9 及更高版本中)。YGC
:表示年轻代垃圾收集次数。YGCT
:表示年轻代垃圾收集总时间。FGC
:表示完全垃圾收集次数。FGCT
:表示完全垃圾收集总时间。GCT
:表示垃圾收集总时间。
理解这些指标可以帮助你诊断 JVM 的性能问题,比如频繁的垃圾收集或内存泄漏。
jstack
jstack
是一个 Java 工具,用于生成 Java 进程的线程快照。它能帮助你诊断挂起(hang)或响应慢的应用程序,通过展示每个线程的堆栈跟踪信息,可以分析线程的状态以及它们在做什么。这对于理解线程间交互、死锁情况、长时间运行的请求等问题非常有用。
使用 jstack
基本语法
jstack [options] <pid>
<pid>
是 Java 进程的 ID。[options]
可以是多个可选参数,用来控制输出的格式或显示的信息。
常见选项
-l
或--long
:产生详细的堆栈跟踪信息,包括锁信息和监视器信息。-F
或--file
:当通过 PID 无法访问 Java 进程时,可以指定 core 文件或转储文件作为输入。-m
或--mixed
:显示混合模式堆栈,即 Java 和本地方法的堆栈跟踪。-h
或--help
:显示帮助信息。
如何使用
-
查找 Java 进程的 PID:
首先,你需要确定 Java 进程的 PID。你可以使用jps
命令来列出所有正在运行的 Java 进程。 -
生成线程堆栈信息:
执行jstack
命令,将找到的 PID 作为参数传递给它。例如:
jstack 1234 > stacktrace.txt
这里
1234
是你的 Java 进程的 PID。> stacktrace.txt
将输出重定向到一个文本文件,便于后续分析。 -
分析输出:
jstack
输出将包含每个线程的堆栈跟踪,包括线程 ID、线程名称、线程状态以及调用栈。通过分析这些信息,你可以判断哪些线程处于阻塞状态、哪些线程持有锁、哪些线程可能造成死锁等。
输出解读
jstack
的输出通常会显示如下信息:
- 线程 ID 和名称
- 线程状态(如 RUNNABLE, BLOCKED, WAITING 等)
- Java 方法调用栈
- 锁信息(如果使用了
-l
参数)
例如,你可能会看到类似这样的输出:
"main" #1 prio=5 os_prio=0 tid=0x00007f6b47fff800 nid=0x3500 waiting on condition [0x00007f6b47f8c000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x00000007a29e6488> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)
at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
通过这些信息,你可以识别出线程在哪个方法上被阻塞,或者是否在等待某种条件,从而定位问题所在。
原文地址:https://blog.csdn.net/Casual_Lei/article/details/140591245
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!