当前位置: 首页 > news >正文

JVM调优常用命令

1.jps

专门用于查找 Java 进程。

1.1 基本语法

jps [options] [hostid]

[options]:命令选项,用于控制输出内容。

[hostid]:指定远程主机,可以省略(主要用于查看本机进程)。

1.2 常用选项(options)

选项全称作用描述
-qquiet只输出进程的 PID,不显示主类名称
-mmain输出传递给 main() 方法的参数
-llong输出应用程序主类的完整包名应用程序 JAR 文件的完整路径名
-vversion输出传递给 JVM 的参数(非常有用,常用于排查启动参数问题)
-V输出通过 .hotspotrc 文件或 -XX:Flags= 指定的参数

1.3 使用示例

1.3.1基本使用

jps

1.3.2 显示完整名称 (-l)

jps -l

1.3.3 显示 JVM 参数 (-v)

jps -v

1.4.4 显示 main 方法的参数 (-m)
jps -m

1.4.5 组合使用选项

常用的组合是 -mlv,可以一次性看到所有信息。

jps -mlv

1.4.6 只显示 PID (-q)

jps -q

2. jmap

此命令可以用来查看内存信息,实例个数以及占用内存大小。

2.1 基本语法

jmap [option] <pid>        # 最常用的形式,对指定PID的Java进程操作
jmap [option] <executable <core>   # 与核心文件交互
jmap [option] [server_id@]<remote server IP or hostname> # 与远程服务器交互

2.2  常用选项(options)

选项作用描述备注
-dump:[live,]format=b,file=<filename>生成堆转储快照(核心功能)live:只转储存活的对象,会触发 Full GC。
format=b:指定二进制格式。
file:指定输出文件名。
-heap显示Java堆的详细信息包括GC算法、堆配置、各代内存使用情况。
-histo[:live]显示堆中对象的统计信息live:只统计存活的对象,会触发 Full GC。
显示每个类的实例数、内存占用、类全名。
-clstats显示类加载器的统计信息输出类加载器及其加载的类的元数据大小。
-finalizerinfo显示正在等待 Finalizer 线程执行 finalize 方法的对象如果队列不为空,说明有对象在等待被回收。
-F强制模式当 jmap -dump 或 jmap -histo 没有响应时,与 -dump 或 -histo 一起使用。(强制操作有风险,可能导致进程僵死)

2.3 使用示例

2.3.1 生成堆转储文件

#触发Full GC
jmap -dump:live,format=b,file=myheapdump.hprof 3947#不触发Full GC
jmap -dump:format=b,file=myheapdump.hprof 3947

会在当前目录下生成一个名为 myheapdump.hprof 的二进制文件。

使用相关的分析工具打开(比如 JVisualVM ),可以直观地分析内存泄漏、大对象等问题。

可以设置内存溢出自动导出dump文件(内存很大的时候,可能会导不出来)

1. -XX:+HeapDumpOnOutOfMemoryError

2. -XX:HeapDumpPath=./ (路径)

注意事项:

  • 使用 live 选项会触发一次 Full GC,可能会对线上应用的性能造成短暂影响,请谨慎在生产环境使用。

  • 堆转储文件通常非常大(可达数GB),确保磁盘空间充足。

2.3.2 查看堆内存摘要信息 (-heap)

(mac权限问题使用命令jcmd 3947 GC.heap_info输出的,效果类似呈现可能有所不同)

2.3.3 查看类实例统计信息 (-histo)

# 查看所有对象(包括已死但未回收的)
jmap -histo 3947 | head -20# 只查看存活的对象(会触发Full GC)
jmap -histo:live 3947 | head -20#输出到指定目录
jmap -histo 3947 > ./log.txt
  • | 是管道符,将 jmap -histo 3947 的输出传递给 head -20
  • head 是一个命令行工具,用于显示文件或输入的前几行。
  • -20 表示仅显示前 20 行。(方便查看)

  • num:序号
  • instances:实例数量
  • bytes:占用空间大小
  • class name:类名称

3. jstack

  1. 排查 CPU 占用过高问题:找出哪个线程、哪行代码在疯狂消耗 CPU。

  2. 诊断死锁(Deadlock):自动检测并报告线程间是否存在死锁。

  3. 分析线程阻塞(Blocking)或挂起(Hanging):查看线程为何无法继续执行,比如在等待锁、等待IO、等待网络响应等。

  4. 排查应用无响应:当应用不处理请求时,查看所有线程的状态和调用栈。

  5. 监控线程状态:查看线程总数、守护线程数、线程状态(RUNNABLE, BLOCKED, WAITING, TIMED_WAITING)等。

3.1 基本语法

jstack [options] <pid>        # 最常用的形式,对指定PID的Java进程操作
jstack [options] <executable <core>   # 从核心文件获取线程转储
jstack [options] [server_id@]<remote server IP or hostname> # 连接远程服务器

3.2 常用选项(options)

选项作用描述备注
-F强制生成线程转储当普通的 jstack 命令没有响应时使用(例如进程卡死时)。
-l长列表模式(最常用) 除了堆栈信息外,还显示关于锁的附加信息(如拥有的锁、等待的锁)。强烈建议始终使用此选项
-m混合模式输出 Java 和本地本地(Native C/C++)框架的堆栈信息。用于排查 JNI 代码问题。
-h显示帮助信息

3.3 使用示例

jstack -l 3947
2025-09-14 22:03:11
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.333-b02 mixed mode):"nacos-grpc-client-executor-192.168.3.2-1970" #2057 daemon prio=5 os_prio=31 tid=0x00007f7fbb134000 nid=0x1c07b waiting on condition [0x000000030fa60000]java.lang.Thread.State: TIMED_WAITING (parking)at sun.misc.Unsafe.park(Native Method)- parking to wait for  <0x000000079682cdb0> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2078)at java.util.concurrent.LinkedBlockingQueue.poll(LinkedBlockingQueue.java:467)at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1073)at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)at java.lang.Thread.run(Thread.java:750)Locked ownable synchronizers:- None
头部信息:时间、JVM 信息
2025-09-14 22:03:11
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.333-b02 mixed mode):
线程信息列表

"nacos-grpc-client-executor-192.168.3.2-1961" #2048 daemon prio=5 os_prio=31 tid=0x00007f7fbb943800 nid=0xb85f waiting on condition [0x000000030fa60000]java.lang.Thread.State: TIMED_WAITING (parking)at sun.misc.Unsafe.park(Native Method)- parking to wait for  <0x000000079682cdb0> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2078)at java.util.concurrent.LinkedBlockingQueue.poll(LinkedBlockingQueue.java:467)at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1073)at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)at java.lang.Thread.run(Thread.java:750)Locked ownable synchronizers:- None
"http-nio-8080-exec-1" #32 daemon prio=5 os_prio=31 tid=0x00007f9d8a810000 nid=0x5a03 runnable [0x0000700008bb9000]java.lang.Thread.State: RUNNABLEat java.net.SocketInputStream.socketRead0(Native Method)at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)at java.net.SocketInputStream.read(SocketInputStream.java:171)at java.net.SocketInputStream.read(SocketInputStream.java:141)at org.apache.coyote.http11.Http11InputBuffer.fill(Http11InputBuffer.java:794)at org.apache.coyote.http11.Http11InputBuffer.parseRequestLine(Http11InputBuffer.java:358)at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:447)at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:893)at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1722)at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)- locked <0x0000000740008f58> (a org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper)at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)at java.lang.Thread.run(Thread.java:748)Locked ownable synchronizers:- None

关键字段解析:

  • 线程名"nacos-grpc-client-executor-192.168.3.2-1961"(通常能看出线程用途)

  • 守护线程daemon(如果是,则会标明)

  • 优先级prio=5

  • 线程状态java.lang.Thread.State: TIMED_WAITING (parking)

  • nidnid=0xb85f(Native Thread ID,对应操作系统的线程ID,可用于和 top -Hp <pid> 命令结合查找CPU消耗最高的线程)

  • 调用栈(Stack Trace):显示了该线程当前执行到哪个类的哪个方法。

  • 锁信息- locked <...>(如果有会显示)

  • 正在等待的锁: - waiting on <...>(如果有会显示)

shi

  1. top:找到 CPU 占用最高的 Java 进程 PID。

  2. top -Hp <pid>:查看该进程内所有线程的 CPU 占用情况,找到占用最高的线程 ID(例如 12345)。

  3. 将线程 ID 转换为十六进制printf "%x\n" 12345 -> 得到 0x3039

  4. jstack -l <pid> > thread_dump.log:生成线程转储。

  5. 在 thread_dump.log 中搜索上一步得到的十六进制值 nid=0x3039。找到对应的线程,查看它的调用栈,就能定位到是哪一行代码在疯狂消耗 CPU。

3.4 死锁检测(如果有的话)

如果 jstack 检测到死锁,它会在转储的最后清晰地报告:

Found one Java-level deadlock:
=============================
"Thread-1":waiting to lock monitor 0x00007faa8b008f00 (object 0x00000007400c6d98, a java.lang.Object),which is held by "Thread-0"
"Thread-0":waiting to lock monitor 0x00007faa8b00a100 (object 0x00000007400c6da8, a java.lang.Object),which is held by "Thread-1"Java stack information for the threads listed above:
===================================================
"Thread-1":at com.example.DeadlockDemo.methodB(DeadlockDemo.java:30)- waiting to lock <0x00000007400c6d98> (a java.lang.Object)- locked <0x00000007400c6da8> (a java.lang.Object)at com.example.DeadlockDemo.run(DeadLockDemo.java:40)
"Thread-0":at com.example.DeadlockDemo.methodA(DeadlockDemo.java:16)- waiting to lock <0x00000007400c6da8> (a java.lang.Object)- locked <0x00000007400c6d98> (a java.lang.Object)at com.example.DeadlockDemo.run(DeadLockDemo.java:35)


文章转载自:

http://661PoWiM.frsrk.cn
http://daW0vx5L.frsrk.cn
http://osyY6xZ4.frsrk.cn
http://KUAowZEI.frsrk.cn
http://dzOoQRUp.frsrk.cn
http://cnxEnf5O.frsrk.cn
http://SKDlkhD2.frsrk.cn
http://4jhuwtP8.frsrk.cn
http://6EWjUIV4.frsrk.cn
http://SvWt2vSj.frsrk.cn
http://7BXLCySv.frsrk.cn
http://CvSIpotL.frsrk.cn
http://6EUzOxLd.frsrk.cn
http://8ZhwKzST.frsrk.cn
http://PE4lmRDP.frsrk.cn
http://3rRCNk5G.frsrk.cn
http://QCAfgRUq.frsrk.cn
http://lFWcwSPp.frsrk.cn
http://gRxHcFxl.frsrk.cn
http://1saSj0n8.frsrk.cn
http://bjz2aDWf.frsrk.cn
http://0RtBkiEp.frsrk.cn
http://nXdxuEHx.frsrk.cn
http://Dw1LA5s2.frsrk.cn
http://ldiN0dzw.frsrk.cn
http://a1E6N7mr.frsrk.cn
http://IyMR2Kmj.frsrk.cn
http://OBL1J08n.frsrk.cn
http://1jhtCnUQ.frsrk.cn
http://RCVzUM7S.frsrk.cn
http://www.dtcms.com/a/383159.html

相关文章:

  • 文心快码Comate - 百度推出的AI编码助手
  • 做一个RBAC权限
  • Debian13下使用 Vim + Vimspector + ST-LINK v2.1 调试 STM32F103 指南
  • 临床研究三千问——临床研究体系的4个核心(9)
  • 高光谱成像在回收塑料、纺织、建筑废料的应用
  • LeetCode 2348.全0子数组的数目
  • OCSP CDN HTTPS OTA
  • 1.2.3、从“本事务读”和“阻塞别的事务”角度看 Mysql 的事务和锁
  • MySQL C API 的 mysql_init 函数深度解析
  • 第10课:实时通信与事件处理
  • 33.网络基础概念(三)
  • Spark专题-第一部分:Spark 核心概述(1)-Spark 是什么?
  • 使用buildroot创建自己的linux镜像
  • MapReduce核心知识点总结:分布式计算的基石
  • 当大模型走向“赛场”:一场跨越教育、医疗与星辰的AI创新马拉松
  • 2025年IEEE TCE SCI2区,不确定环境下多无人机协同任务的时空优化动态路径规划,深度解析+性能实测
  • Python 上下文管理器:优雅解决资源管理难题
  • 主流反爬虫、反作弊防护与风控对抗手段
  • C语言柔性数组详解与应用
  • 【C++】22. 封装哈希表实现unordered_set和unordered_map
  • ARM Cortex-M 中的 I-CODE 总线、D-CODE 总线和系统总线
  • HTML5和CSS3新增的一些属性
  • 用C语言打印乘法口诀表
  • Docker desktop安装Redis Cluster集群
  • 拼多多返利app的服务自动扩缩容策略:基于K8s HPA的弹性架构设计
  • 每日前端宝藏库 | Lodash
  • LeetCode 978.最长湍流子数组
  • Java连接电科金仓数据库(KingbaseES)实战指南
  • 2025 年 AI 与网络安全最新趋势深度报告
  • PDF发票提取工具快速导出Excel表格