JVM 性能调优 -- JVM常用调优工具【jps、jstack、jmap、jstats 命令】

前言:

前面我们分析怎么去预估系统资源,怎么去设置 JVM 参数以及怎么去看 GC 日志,本篇我们分享一些常用的 JVM 调优工具,我们在进行 JVM 调优的时候,通常需要借助一些工具来对系统的进行相关分析,从而确定当前的 JVM 是否需要进行调优,以及有哪些问题需要优化。

JVM 系列文章传送门

初识 JVM(Java 虚拟机)

深入理解 JVM(Java 虚拟机)

一文搞懂 JVM 垃圾回收(JVM GC)

深入理解 JVM 垃圾回收算法

一文搞懂 JVM 垃圾收集器

JVM 调优相关参数

JVM 场景面试题【强烈推荐】

JVM 性能调优 – 线上应用 JVM 内存的的预估设置【实战】

JVM 性能调优 – 线上应用 JVM 内存调优【实战】

JVM 性能调优 – 模拟触发 Minor GC【GC 日志分析】

JVM 性能调优 – 模拟触发 Minor GC(2)【GC 日志分析】

JVM 性能调优 – CMS 垃圾回收器 GC 日志分析【Full GC】

JVM 调优工具认识

辅助 JVM 调优的工具有很多种,从宏观上我们可以分为两类,分别是 Java 自带的相关工具和第三方辅助调优工具,本篇我们只讨论 Java 自带的 JVM 调优工具。

JVM 自带的调优工具又可以分为两类,如下:

命令行工具

  • jps:查看进程的信息。
  • jinfo:查看进程基本信息,包括启动参数、垃圾回收器等信息。
  • jstack:查看 Java 进程的线程的堆栈信息。
  • jmap:主要用于生成堆转内存快照。
  • jhat:JVM 堆转储快照分析工具,一般和 jmap 结合使用,使用 jmap 把进程内存使用情况 dump 到文件中,再用 jhat 进行分析查看。
  • jstat:JVM 统计监测工具。

可视化工具

  • jconsole:用于对 JVM 的内存、线程、类进行监控,是一个基于 JMX 的 GUI 性能监控工具。
  • jsisualvm:能够监控 CPU、内存使用情况,也可以查看程序运行时候的 GC 情况。

以上就是 Java 提供的一些常用的 JVM 调优辅助工具。

jps 命令

jps 命令主要是查看正在运行的 Java 进程信息,用法如下:

jps

执行结果如下:

14192 nacos-server.jar
27680 RemoteMavenServer36
18852
19508 Launcher
31108 Jps
12232
18280 RemoteMavenServer36
30332 Launcher
jps -l

执行结果如下:

14192 D:\meto\study\nacos\nacos-server-2.3.2\nacos\target\nacos-server.jar
27680 org.jetbrains.idea.maven.server.RemoteMavenServer36
18852
19508 org.jetbrains.jps.cmdline.Launcher
20020 sun.tools.jps.Jps
12232
18280 org.jetbrains.idea.maven.server.RemoteMavenServer36
30332 org.jetbrains.jps.cmdline.Launcher

对比 jps 和 jps -l 命令的区别就是 jps -l 可以看到完整的包路径,而 JPS 命令看不到,两个命令都可以看到进程号。

jinfo 命令

jinfo 命令需要用于实时查看正在运行的 Java 进程基本信息,包括启动参数、垃圾回收器等信息。

jinfo 命令的执行方式是:jinfo pid,执行如下:

jinfo 14192

执行结果如下:

Attaching to process ID 14192, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.121-b13
Java System Properties:java.vendor = Oracle Corporation
sun.java.launcher = SUN_STANDARD
catalina.base = D:\meto\study\nacos\nacos-server-2.3.2\nacos\bin
sun.management.compiler = HotSpot 64-Bit Tiered Compilers
catalina.useNaming = false
nacos.local.ip = 192.168.123.132
loader.path = D:\meto\study\nacos\nacos-server-2.3.2\nacos/plugins,D:\meto\study\nacos\nacos-server-2.3.2\nacos/plugins/health,D:\meto\study\nacos\nacos-server-2.3.2\nacos/plugins/cmdb,D:\meto\study\nacos\nacos-server-2.3.2\nacos/plugins/selector
os.name = Windows 10
sun.boot.class.path = D:\tool\jdk\jdk\jre\lib\resources.jar;D:\tool\jdk\jdk\jre\lib\rt.jar;D:\tool\jdk\jdk\jre\lib\sunrsasign.jar;D:\tool\jdk\jdk\jre\lib\jsse.jar;D:\tool\jdk\jdk\jre\lib\jce.jar;D:\tool\jdk\jdk\jre\lib\charsets.jar;D:\tool\jdk\jdk\jre\lib\jfr.jar;D:\tool\jdk\jdk\jre\classes
sun.desktop = windows
java.vm.specification.vendor = Oracle Corporation
java.runtime.version = 1.8.0_121-b13
user.name = user.name
user.language = zh
sun.boot.library.path = D:\tool\jdk\jdk\jre\bin
com.zaxxer.hikari.pool_number = 1
CONSOLE_LOG_CHARSET = GBK
nacos.home = D:\meto\study\nacos\nacos-server-2.3.2\nacos
PID = 14192
java.version = 1.8.0_121
user.timezone = Asia/Shanghai
sun.arch.data.model = 64
java.endorsed.dirs = D:\tool\jdk\jdk\jre\lib\endorsed
sun.cpu.isalist = amd64
sun.jnu.encoding = GBK
file.encoding.pkg = sun.io
file.separator = \
java.specification.name = Java Platform API Specification
java.class.version = 52.0
nacos.standalone = true
user.country = CN
java.home = D:\tool\jdk\jdk\jre
java.vm.info = mixed mode
os.version = 10.0
path.separator = ;
java.vm.version = 25.121-b13
user.variant =
java.protocol.handler.pkgs = org.springframework.boot.loader
java.awt.printerjob = sun.awt.windows.WPrinterJob
sun.io.unicode.encoding = UnicodeLittle
awt.toolkit = sun.awt.windows.WToolkit
sun.stdout.encoding = ms936
user.script =
user.home = C:\Users\Administrator
java.specification.vendor = Oracle Corporation
java.library.path = D:\tool\jdk\jdk\bin;C:\Windows\Sun\Java\bin;C:\Windows\system32;C:\Windows;C:\ProgramData\Oracle\Java\javapath;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Windows\System32\OpenSSH\;D:\tool\jdk\jdk\bin;D:\tool\jdk\jdk\jre\bin;D:\tool\git\Git\cmd;D:\tool\svn\bin;D:\tool\maven\apache-maven-3.8.4-bin\apache-maven-3.8.4\bin;D:\tool\web\nodejs\;C:\Users\Administrator\AppData\Local\Microsoft\WindowsApps;C:\Users\Administrator\AppData\Roaming\npm;D:\tool\web\webstorm\Microsoft VS Code\bin;D:\tool\idea202103\IntelliJ IDEA 2021.3.3\bin;;.
java.vendor.url = http://java.oracle.com/
spring.beaninfo.ignore = true
java.vm.vendor = Oracle Corporation
java.runtime.name = Java(TM) SE Runtime Environment
sun.java.command = D:\meto\study\nacos\nacos-server-2.3.2\nacos\target\nacos-server.jar --spring.config.additional-location=file:D:\meto\study\nacos\nacos-server-2.3.2\nacos/conf/ --logging.config=D:\meto\study\nacos\nacos-server-2.3.2\nacos/conf/nacos-logback.xml nacos.nacos
java.class.path = D:\meto\study\nacos\nacos-server-2.3.2\nacos\target\nacos-server.jar
nacos.function.mode = All
java.vm.specification.name = Java Virtual Machine Specification
java.vm.specification.version = 1.8
catalina.home = D:\meto\study\nacos\nacos-server-2.3.2\nacos\bin
sun.cpu.endian = little
sun.os.patch.level =
java.awt.headless = true
java.io.tmpdir = C:\Users\ADMINI~1\AppData\Local\Temp\
FILE_LOG_CHARSET = GBK
java.vendor.url.bug = http://bugreport.sun.com/bugreport/
os.arch = amd64
java.awt.graphicsenv = sun.awt.Win32GraphicsEnvironment
java.ext.dirs = D:\tool\jdk\jdk\jre\lib\ext;C:\Windows\Sun\Java\lib\ext
user.dir = D:\meto\study\nacos\nacos-server-2.3.2\nacos\bin
line.separator =java.vm.name = Java HotSpot(TM) 64-Bit Server VM
nacos.mode = stand alone
sun.stderr.encoding = ms936
file.encoding = GBK
java.specification.version = 1.8VM Flags:
Non-default VM flags: -XX:CICompilerCount=4 -XX:InitialHeapSize=536870912 -XX:MaxHeapSize=536870912 -XX:MaxNewSize=268435456 -XX:MinHeapDeltaBytes=524288 -XX:NewSize=268435456 -XX:OldSize=268435456 -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseFastUnorderedTimeStamps -XX:-UseLargePagesIndividualAllocation -XX:+UseParallelGC
Command line:  -Xms512m -Xmx512m -Xmn256m -Dnacos.standalone=true -Dloader.path=D:\meto\study\nacos\nacos-server-2.3.2\nacos/plugins,D:\meto\study\nacos\nacos-server-2.3.2\nacos/plugins/health,D:\meto\study\nacos\nacos-server-2.3.2\nacos/plugins/cmdb,D:\meto\study\nacos\nacos-server-2.3.2\nacos/plugins/selector -Dnacos.home=D:\meto\study\nacos\nacos-server-2.3.2\nacos

可以看到执行 jinfo 命令打印了非常多的信息,包括 Java 版本、环境信息、JVM 参数等非常多的信息,这些信息并不是我们都要关注的,如果我们想要少看到一些信息,可以使用 jinfo -flags 线程pid 命令。

jinfo -flags 14192

执行结果如下:

Attaching to process ID 14192, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.121-b13
Non-default VM flags: -XX:CICompilerCount=4 -XX:InitialHeapSize=536870912 -XX:MaxHeapSize=536870912 -XX:MaxNewSize=268435456 -XX:MinHeapDeltaBytes=524288 -XX:NewSize=268435456 -XX:OldSize=268435456 -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseFastUnorderedTimeStamps -XX:-UseLargePagesIndividualAllocation -XX:+UseParallelGC
Command line:  -Xms512m -Xmx512m -Xmn256m -Dnacos.standalone=true -Dloader.path=D:\meto\study\nacos\nacos-server-2.3.2\nacos/plugins,D:\meto\study\nacos\nacos-server-2.3.2\nacos/plugins/health,D:\meto\study\nacos\nacos-server-2.3.2\nacos/plugins/cmdb,D:\meto\study\nacos\nacos-server-2.3.2\nacos/plugins/selector -Dnacos.home=D:\meto\study\nacos\nacos-server-2.3.2\nacos

可以看到执行 jinfo -flags 命令后打印的信息少了很多,主要都是 JVM 的一些参数信息,这些信息是我们需要重点关注的信息。

jstack 命令

jstack 命令,主要用于查看 Java 进程内线程的堆栈信息,用法如下:

jstack 进程id

进程 id 就是 Java 进行的 id,执行命令如下:

jstack 114684

执行结果如下:

2024-11-20 19:51:55
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.251-b08 mixed mode):"Keep-Alive-Timer" #13930 daemon prio=8 os_prio=0 tid=0x00007fb22c0de800 nid=0x1834c waiting on condition [0x00007fb1a9b93000]java.lang.Thread.State: TIMED_WAITING (sleeping)at java.lang.Thread.sleep(Native Method)at sun.net.www.http.KeepAliveCache.run(KeepAliveCache.java:172)at java.lang.Thread.run(Thread.java:748)"pool-3-thread-17" #10344 prio=5 os_prio=0 tid=0x00007fb2562f0000 nid=0x1068a waiting on condition [0x00007fb1ad9d1000]java.lang.Thread.State: WAITING (parking)at sun.misc.Unsafe.park(Native Method)- parking to wait for  <0x00000000dd9903f0> (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:1074)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:748)"org.springframework.amqp.rabbit.RabbitListenerEndpointContainer#6-2" #10343 prio=5 os_prio=0 tid=0x00007fb1e0de2000 nid=0x1067e waiting on condition [0x00007fb1a928a000]java.lang.Thread.State: TIMED_WAITING (parking)at sun.misc.Unsafe.park(Native Method)- parking to wait for  <0x00000000dd993d78> (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 org.springframework.amqp.rabbit.listener.BlockingQueueConsumer.nextMessage(BlockingQueueConsumer.java:499)at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.doReceiveAndExecute(SimpleMessageListenerContainer.java:927)at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.receiveAndExecute(SimpleMessageListenerContainer.java:913)at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.access$1600(SimpleMessageListenerContainer.java:81)at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.mainLoop(SimpleMessageListenerContainer.java:1284)at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.run(SimpleMessageListenerContainer.java:1190)at java.lang.Thread.run(Thread.java:748)"pool-3-thread-16" #10342 prio=5 os_prio=0 tid=0x00007fb256f9a800 nid=0x1067b waiting on condition [0x00007fb1a4f53000]java.lang.Thread.State: WAITING (parking)at sun.misc.Unsafe.park(Native Method)- parking to wait for  <0x00000000dd9903f0> (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:1074)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:748)"pool-3-thread-15" #10341 prio=5 os_prio=0 tid=0x00007fb256809800 nid=0x1067a waiting on condition [0x00007fb1acfc7000]java.lang.Thread.State: WAITING (parking)at sun.misc.Unsafe.park(Native Method)- parking to wait for  <0x00000000dd9903f0> (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:1074)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:748)"pool-3-thread-14" #10340 prio=5 os_prio=0 tid=0x00007fb256542800 nid=0x10679 waiting on condition [0x00007fb1af1e1000]java.lang.Thread.State: WAITING (parking)at sun.misc.Unsafe.park(Native Method)- parking to wait for  <0x00000000dd9903f0> (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:1074)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:748)"pool-3-thread-13" #10339 prio=5 os_prio=0 tid=0x00007fb22801b000 nid=0x10677 waiting on condition [0x00007fb1aded6000]java.lang.Thread.State: TIMED_WAITING (parking)at sun.misc.Unsafe.park(Native Method)- parking to wait for  <0x00000000dd9963e8> (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.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1093)at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:809)at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1074)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:748)"AMQP Connection 10.100.40.29:5672" #10338 prio=5 os_prio=0 tid=0x00007fb22800a000 nid=0x10676 runnable [0x00007fb1adfd7000]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 java.io.BufferedInputStream.fill(BufferedInputStream.java:246)at java.io.BufferedInputStream.read(BufferedInputStream.java:265)- locked <0x00000000dd995db0> (a java.io.BufferedInputStream)at java.io.DataInputStream.readUnsignedByte(DataInputStream.java:288)at com.rabbitmq.client.impl.Frame.readFrom(Frame.java:91)at com.rabbitmq.client.impl.SocketFrameHandler.readFrame(SocketFrameHandler.java:184)- locked <0x00000000dd995d90> (a java.io.DataInputStream)at com.rabbitmq.client.impl.AMQConnection$MainLoop.run(AMQConnection.java:598)at java.lang.Thread.run(Thread.java:748)"org.springframework.amqp.rabbit.RabbitListenerEndpointContainer#4-2" #10334 prio=5 os_prio=0 tid=0x00007fb1dc02d800 nid=0x10671 waiting on condition [0x00007fb1ae0d8000]java.lang.Thread.State: TIMED_WAITING (parking)at sun.misc.Unsafe.park(Native Method)- parking to wait for  <0x00000000dd991b78> (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 org.springframework.amqp.rabbit.listener.BlockingQueueConsumer.nextMessage(BlockingQueueConsumer.java:499)at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.doReceiveAndExecute(SimpleMessageListenerContainer.java:927)at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.receiveAndExecute(SimpleMessageListenerContainer.java:913)at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.access$1600(SimpleMessageListenerContainer.java:81)at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.mainLoop(SimpleMessageListenerContainer.java:1284)at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.run(SimpleMessageListenerContainer.java:1190)at java.lang.Thread.run(Thread.java:748)"org.springframework.amqp.rabbit.RabbitListenerEndpointContainer#2-2" #10331 prio=5 os_prio=0 tid=0x00007fb1c8030800 nid=0x1066f waiting on condition [0x00007fb1adad2000]java.lang.Thread.State: TIMED_WAITING (parking)at sun.misc.Unsafe.park(Native Method)- parking to wait for  <0x00000000dd992c88> (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 org.springframework.amqp.rabbit.listener.BlockingQueueConsumer.nextMessage(BlockingQueueConsumer.java:499)at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.doReceiveAndExecute(SimpleMessageListenerContainer.java:927)at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.receiveAndExecute(SimpleMessageListenerContainer.java:913)at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.access$1600(SimpleMessageListenerContainer.java:81)at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.mainLoop(SimpleMessageListenerContainer.java:1284)at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.run(SimpleMessageListenerContainer.java:1190)at java.lang.Thread.run(Thread.java:748)"org.springframework.amqp.rabbit.RabbitListenerEndpointContainer#0-2" #10332 prio=5 os_prio=0 tid=0x00007fb1b8031000 nid=0x1066e waiting on condition [0x00007fb1af2e2000]java.lang.Thread.State: TIMED_WAITING (parking)at sun.misc.Unsafe.park(Native Method)- parking to wait for  <0x00000000dd994e98> (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 org.springframework.amqp.rabbit.listener.BlockingQueueConsumer.nextMessage(BlockingQueueConsumer.java:499)at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.doReceiveAndExecute(SimpleMessageListenerContainer.java:927)at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.receiveAndExecute(SimpleMessageListenerContainer.java:913)at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.access$1600(SimpleMessageListenerContainer.java:81)at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.mainLoop(SimpleMessageListenerContainer.java:1284)at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.run(SimpleMessageListenerContainer.java:1190)at java.lang.Thread.run(Thread.java:748)

可以看到执行 jstack 命令后,输出了线程堆栈信息,因为会输出当前进程中的所有线程堆栈信息,会非常多,这里只贴出来了一小部分。

以上就是 jstack 命令的使用方法,jstack 命令主要用于查看 Java 进程对应的线程运行情况。

jmap 命令

jmap 命令非常实用,主要用于生成堆转内存快照,方便查看内存的使用情况,用法如下:

jmap -heap  114684

执行结果如下:

Attaching to process ID 114684, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.251-b08using thread-local object allocation.
Parallel GC with 4 thread(s)//堆配置
Heap Configuration://空闲堆空间的最小百分比MinHeapFreeRatio         = 0//空闲堆空间的最大百分比MaxHeapFreeRatio         = 100//堆空间允许的最大值MaxHeapSize              = 1073741824 (1024.0MB)//新生代堆空间的默认值NewSize                  = 357564416 (341.0MB)//新生代堆空间允许的最大值MaxNewSize               = 357564416 (341.0MB)//老年代堆空间的默认值OldSize                  = 716177408 (683.0MB)//新生代与老年代的堆空间比值 新生代:老年代=1:2NewRatio                 = 2//Eden 区域和 Survivor 区域的比值 8:1:1SurvivorRatio            = 8//元空间默认值MetaspaceSize            = 268435456 (256.0MB)//压缩卷使用空间大小CompressedClassSpaceSize = 528482304 (504.0MB)//元空间允许的最大值MaxMetaspaceSize         = 536870912 (512.0MB)//使用 G1 垃圾回收器时 每个 Region 空间的大小G1HeapRegionSize         = 0 (0.0MB)//JVM 堆中各个区域内存使用情况
Heap Usage:
PS Young Generation
Eden Space:capacity = 352321536 (336.0MB)used     = 34211200 (32.6263427734375MB)free     = 318110336 (303.3736572265625MB)9.710221063523065% used
From Space:capacity = 2621440 (2.5MB)used     = 1721936 (1.6421661376953125MB)free     = 899504 (0.8578338623046875MB)65.6866455078125% used
To Space:capacity = 2621440 (2.5MB)used     = 0 (0.0MB)free     = 2621440 (2.5MB)0.0% used
PS Old Generationcapacity = 716177408 (683.0MB)used     = 500095856 (476.92857360839844MB)free     = 216081552 (206.07142639160156MB)69.82848808322086% used67973 interned Strings occupying 6972816 bytes.

jmap 命令不仅可以直接查看当前堆内存情况的用法,还有一个重要的用途是用来导出 dump 文件。

使用 jmap 导出 dump 文件,用法如下:

jmap -dump:format=b,file=heap.hprof <pid>
  • format=b:表示以 hprof 二进制格式转储 Java 堆的内存。
  • file=heap.hprof: heap.hprof 是你定义的快照 dump 文件的文件名。
  • :Java 进程 id。
jmap -dump:format=b,file=heap.hprof <pid>

演示案例如下:

jmap -dump:format=b,file=/tmp/mydump.hprof 114684

执行结果如下:

Dumping heap to /tmp/mydump.hprof ...
Heap dump file created

去 tmp 目录下查询文件结果如下:
在这里插入图片描述

jmap 命令生成的 dump 文件是一个进程或系统在某一给定时间的快照,比如在进程崩溃时,我们可以通过 jmap 命令生成 dump 文件方便进行问题排查,dump 文件中包含了程序运行的线程信息、堆栈调用信息、异常信息等。

jhat 命令

jhat 命令的作用就是分析 jmap 转储的 dump 文件。

使用演示如下:

jhat mydump.hprof 

命令执行结果如下:

Reading from mydump.hprof...
Dump file created Wed Nov 20 17:25:56 CST 2024
Snapshot read, resolving...
Resolving 8852631 objects...
Chasing references, expect 1770 dots..........................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
Eliminating duplicate references..........................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
Snapshot resolved.
Started HTTP server on port 7000
Server is ready.

命令执行完成后,我们看到了这么一句话:Started HTTP server on port 7000,也就是在本机服务器的 7000 端口上运行了一个小程序,我们可以通过 7000 端口进行访问,其实在执行 jhat 命令后,会启动一个内置的 HTTP 服务器,分析 dump 文件并将结果以HTML形式展示。

我们在浏览器访问如下:

在这里插入图片描述

jhat 命令的分享就到这里啦。

jstat 命令

jstat 是 JDK 自带的一个轻量级 JVM 调优工具,全称 “Java Virtual Machine statistics monitoring tool”,主要利用 JVM 内建的指令对 Java 应用程序的资源和性能进行实时的命令行的监控,包括了对 JVM 堆的各个空间的监控以及垃回收的相关信息统计,常用命令如下(pid 是 Java 应用进程id):

  • jstat -class pid:查看 Java 进程加载的 class 数量,以及所占空间信息。
  • jstat -compiler pid: 查看 Java 进程 JVM 实时编译信息。
  • jstat -gc pid:查看 Java 进程的 gc 相关信息。
  • jstat -gccapacity pid:查看 Java 进程内存中堆内存的大小分布。
  • jstat -gccause pid:查看 Java 进程有关垃圾收集的信息。
  • jstat -gcnew pid:查看 Java 进程中 JVM 年轻代的对象信息。
  • jstat -gcnewcapacity pid:查看 Java 进程中 JVM 年轻代的空间大小。
  • jstat -gcold pid:查看 Java 进程中 JVM 老年代的空间大小。
  • jstat -gcoldcapacity pid:查看 Java 进程中 JVM 老年代容量大小统计。
  • jstat -gcmetacapacity pid:查看 Java 进程中 JVM 元空间信息统计。
  • jstat -gcutil pid:查看 Java 进程中 JVM 垃圾收集信息统计。
  • jstat -printcompilation pid:查看 JVM 编译方法的统计。

jstat -class pid 命令演示:

jstat -class 114368

执行结果如下:

Loaded  Bytes  Unloaded  Bytes     Time   28132 51810.5        0     0.0      41.06

结果分析:

  • Loaded:装载的类的数量,这里是 28132 个类。
  • Bytes:装载的字节数,这里是 51810.5 字节。
  • Unloaded:卸载的类的数量,没有被卸载的类。
  • Bytes:卸载的类字节数,卸载的类的字节数。
  • Time:装载和卸载类使用的时间,这里是 41.06秒。

jstat -compiler pid 命令演示:

jstat -compiler 114368

执行结果如下:

Compiled Failed Invalid   Time   FailedType FailedMethod35011      1       0   133.75          1 com/alibaba/csp/sentinel/util/TimeUtil$1 run

结果分析:

  • Compiled:编译执行的任务数量,这里是 35011 个。
  • Failed:编译失败的任务数量,这里是 1个。
  • Invalid:编译任务执行失效的数量,这里 0个。
  • Time:编译任务消耗的时间,这里是 133.75秒。
  • FailedMethod:最后一个编译失败任务所在的类及方法。

jstat -gc pid 命令演示:

jstat -gc 114368

执行结果如下:

 S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT     GCT   
1536.0 1536.0  0.0   368.0  346112.0 214732.0  699392.0   597598.7  169856.0 159867.7 20864.0 19147.1    297    4.072   0      0.000    4.072

结果分析:

  • S0C:Survivor From 区空间容量,单位 KB。
  • S1C:Survivor To 区空间容量,单位 KB。
  • S0U:Survivor From 区空间已经使用的容量,单位 KB。
  • S1U:Survivor To 区空间已经使用的容量,单位 KB。
  • EC:Eden 区域空间总容量,单位 KB。
  • EU:Eden 区域空间已使用总容量,单位 KB。
  • OC:Old 区域空间总容量,单位 KB。
  • OU:Old 区域空间已经使用的容量,单位 KB。
  • MC:元空间 Metaspace 空间总容量,单位 KB。
  • MU:元空间 Metaspace 空间已经使用的容量,单位 KB。
  • CCSC:压缩类空间容量,单位 KB。
  • CCSU:压缩类空间已经使用的容量,单位 KB。
  • YGC:Minor GC 回收的空间数量,单位 KB。
  • YGCT:Minor GC 回收消耗的时间,单位 秒。
  • FGC:Full GC 回收的空间数量,单位 KB。
  • FGCT:Full GC 回收消耗的时间,单位 秒。
  • GCT:总 GC 时间,单位 秒。

jstat -gcutil pid 命令演示:

jstat -gcutil pid

举例如下:

jstat -gcutil 114368

执行结果如下:

  S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT     GCT   16.50   0.00  43.55  85.35  94.11  91.77    282    3.898     0    0.000    3.898

jstat -gcutil 命令执行结果解释如下:

  • S0:年轻代中第一个 survivor(From) 区已使用内存占当前容量百分比。
  • S1:年轻代中第二个 survivor(To)区已使用内存占当前容量百分比。
  • E:年轻代中 Eden 区已使用的内存占当前容量百分比。
  • O:老年代已使用的内存占当前容量百分比。
  • M:元数据区已使用的占当前容量百分比。
  • CCS:压缩类空间已使用的占当前容量百分比。
  • YGC :从应用程序启动到采样时年轻代中 GC 次数。
  • YGCT :从应用程序启动到采样时年轻代中 GC 所用时间,单位:秒。
  • FGC :从应用程序启动到采样时 Full GC 的次数。
  • FGCT :从应用程序启动到采样时 Full GC所用时间,单位:秒。
  • GCT:从应用程序启动到采样时 GC 用的总时间,单位:秒。

jstat 命令的使用就分享到这里,还有几个跟 GC 相关的用法大同小异,感兴趣的自己去试一下,各个字段的含义也都差不多,只是从不通过粒度上来进行了分析。

总结:本篇分享 JDK 自带的一些 JVM 调优工具的使用,使用 jps、jinfo、jmap、jstack、jhat、jstat 命令来查看 Java 应用程序的堆栈信息,来辅助我们进行 JVM 调优,关于可视化工具的部分我们下一篇再来分享,希望可以帮助到有需要的朋友们。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/482121.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

linux上离线部署Mysql5.7.22

官网下载地址: https://downloads.mysql.com/archives/community/ Mysql安装步骤&#xff1a; 1.上传mysql安装包 上传 mysql-5.7.22-linux-glibc2.12-x86_64.tar.gz 到服务器指定目录 2.解压缩 tar -zxvf mysql-5.7.22-linux-glibc2.12-x86_64.tar.gz 3.修改名称 mv mysq…

日志与线程池

这里写自定义目录标题 日志Log.hpp测试main.cpp结果 线程池线程池的种类ThreadPool.hpp测试 Task.hpp 和 main.cppTask.hppmain.cpp结果 线程池的单例模式实现方式SignalThreadPool.hpp测试main.cpp 线程安全与重入问题死锁死锁的四个必要条件 日志 日志需要包含的信息 • 时间…

1.1 数据结构的基本概念

1.1.1 基本概念和术语 一、数据、数据对象、数据元素和数据项的概念和关系 数据&#xff1a;是客观事物的符号表示&#xff0c;是所有能输入到计算机中并被计算机程序处理的符号的总称。 数据是计算机程序加工的原料。 数据对象&#xff1a;是具有相同性质的数据元素的集合&…

泷羽sec学习打卡-shell命令5

声明 学习视频来自B站UP主 泷羽sec,如涉及侵权马上删除文章 笔记的只是方便各位师傅学习知识,以下网站只涉及学习内容,其他的都 与本人无关,切莫逾越法律红线,否则后果自负 关于shell的那些事儿-shell5 字符串运算符逻辑运算符之布尔运算符实践是检验真理的唯一标准 字符串运算…

Elasticearch索引mapping写入、查看、修改

作者&#xff1a;京东物流 陈晓娟 一、ES Elasticsearch是一个流行的开源搜索引擎&#xff0c;它可以将大量数据快速存储和检索。Elasticsearch还提供了强大的实时分析和聚合查询功能&#xff0c;数据模式更加灵活。它不需要预先定义固定的数据结构&#xff0c;可以随时添加或修…

Mybatis Plus 增删改查方法(一、增)

先定义一个简单的测试表&#xff0c;执行脚本如下&#xff1a; create table user(id bigint primary key auto_increment,name varchar(255) not null,age int not null default 0 check (age > 0) ); 根据Spingbootmybatisplus的结构根据表自行构建结构&#xff0c;大致…

本地部署 WireGuard 无需公网 IP 实现异地组网

WireGuard 是一个高性能、极简且易于配置的开源虚拟组网协议。使用路由侠内网穿透使其相互通讯。 第一步&#xff0c;服务端&#xff08;假设为公司电脑&#xff09;和客户端&#xff08;假设为公司外的电脑&#xff09;安装部署 WireGuard 1&#xff0c;点此下载&#xff08;…

unity中添加预制体及其基本设置

unity中添加预制体及其基本设置 Unity 中使用预制体的好处使用示例代码解释 Unity 中使用预制体的好处 1. 提高代码复用性 预制体可将一个游戏对象及其所有组件、子对象和设置存储在一个资源文件中&#xff0c;然后在项目中多次使用这个资源。这大大提高了代码的复用性&#x…

给定一个整数可能为正,0,负数,统计这个数据的位数.

题目描述 给定一个整数可能为正,0,负数,统计这个数据的位数. 例如1234567输出7位; -12345678输出8位;0输出1位 代码实现 int main() { long long m; long long n; scanf("%lld",&n); mn; int count0;//位数 do { count; n/10;//舍弃个位 }while(n!0); printf(&…

Linux:文件系统inode

早期&#xff0c;存储文件的设备是磁盘&#xff08;当下的市场几乎都是SSD&#xff09;&#xff0c;但大家习惯的把它们都称为磁盘&#xff0c;磁盘是用来表示区分内存的存储设备。而在操作系统看来&#xff0c;这个存储设备的结构就是一个线性结构&#xff0c;这一点很重要。 …

C++STL之vector(超详细)

CSTL之vector 1.vector基本介绍2.vector重要接口2.1.构造函数2.2.迭代器2.3.空间2.3.1.resize2.3.2.capacity 2.4.增删查找 3.迭代器失效4.迭代器分类 &#x1f31f;&#x1f31f;hello&#xff0c;各位读者大大们你们好呀&#x1f31f;&#x1f31f; &#x1f680;&#x1f68…

深入浅出机器学习中的梯度下降算法

大家好&#xff0c;在机器学习中&#xff0c;梯度下降算法&#xff08;Gradient Descent&#xff09;是一个重要的概念。它是一种优化算法&#xff0c;用于最小化目标函数&#xff0c;通常是损失函数。梯度下降可以帮助找到一个模型最优的参数&#xff0c;使得模型的预测更加准…

树莓派5+文心一言 -> 智能音箱

一、简介 效果&#xff1a;运行起来后&#xff0c;可以连续对话 硬件&#xff1a;树莓派5、麦克风、音箱&#xff0c;成本500-1000 软件&#xff1a;snowboy作为唤醒词、百度语音作为语音识别、brain作为指令匹配、百度文心一言作为对话模块、微软的edge-tts语音合成... 二…

Springboot——SseEmitter流式输出

文章目录 前言SseEmitter 简介测试demo注意点异常一 ResponseBodyEmitter is already set complete 前言 最近做AI类的开发&#xff0c;看到各大AI模型的输出方式都是采取的一种EventStream的方式实现。 不是通常的等接口处理完成后&#xff0c;一次性返回。 而是片段式的处理…

5G学习笔记之随机接入

目录 1. 概述 2. MSG1 2.1 选择SSB 2.2 选择Preamble Index 2.3 选择发送Preamble的时频资源 2.4 确定RA-RNTI 2.5 确定发送功率 3. MSG2 4. MSG3 5. MSG4 6. 其它 6.1 切换中的随机接入 6.2 SI请求的随机接入 6.3 通过PDCCH order重新建立同步 1. 概述 随机接入…

【Linux-多线程】重谈地址空间+内存管理方式

一、背景知识 a.重谈地址空间 我们之前已经说过&#xff0c;CPU内部见的地址&#xff0c;以及我们打印出来的地址都是虚拟地址&#xff1b;物理内存加载到CPU&#xff0c;CPU内执行进程创建内核数据结构&#xff0c;页表等&#xff0c;通过页表映射到物理磁盘上&#xff1b;也…

Spark Optimization —— Reducing Shuffle

Spark Optimization : Reducing Shuffle “Shuffling is the only thing which Nature cannot undo.” — Arthur Eddington Shuffle Shuffle Shuffle I used to see people playing cards and using the word “Shuffle” even before I knew how to play it. Shuffling in c…

Elasticsearch——Java API 操作

Elasticsearch 软件是由Java语言开发的,所以也可以通过JavaAPI的方式对 Elasticsearch服务进行访问。 创建 Maven 项目 我们在 IDEA 开发工具中创建 Maven 项目(模块也可)ES。并修改pom文件&#xff0c;增加Maven依赖关系。 #直接复制在pom文件的<dependencies></de…

量化的8位LLM训练和推理使用bitsandbytes在AMD GPUs上

Quantized 8-bit LLM training and inference using bitsandbytes on AMD GPUs — ROCm Blogs 在这篇博客文章中&#xff0c;我们将介绍bitsandbytes的8位表示方式。正如你将看到的&#xff0c;bitsandbytes的8位表示方式显著地减少了微调和推理大语言模型&#xff08;LLMs&…

自回归(Autoregressive)模型概述

自回归&#xff08;Autoregressive&#xff09;模型概述 自回归&#xff08;Autoregressive&#xff0c;简称AR&#xff09;模型是一类基于“历史数据”来预测未来数据的模型。其核心思想是模型的输出不仅依赖于当前输入&#xff0c;还依赖于先前的输出。自回归模型通常用于时…