JVM进阶调优系列(7)JVM调优监控必备命令、工具集合|实用干货

本文涉及的产品
容器服务 Serverless 版 ACK Serverless,317元额度 多规格
容器镜像服务 ACR,镜像仓库100个 不限时长
容器服务 Serverless 版 ACK Serverless,952元额度 多规格
简介: 本文介绍了JVM调优监控命令及其应用,包括JDK自带工具如jps、jinfo、jstat、jstack、jmap、jhat等,以及第三方工具如Arthas、GCeasy、MAT、GCViewer等。通过这些工具,可以有效监控和优化JVM性能,解决内存泄漏、线程死锁等问题,提高系统稳定性。文章还提供了详细的命令示例和应用场景,帮助读者更好地理解和使用这些工具。

最近读书心得:大道至简,知行合一。利己者存,利他者久。

    按计划,分享整理10篇核心基础相关文章,帮助大家知识巩固。虽然理论有点枯燥,但是基础不牢地动山摇大家都懂,还是那句话,磨刀不误砍柴工,好事多磨。大家耐心继续看下去,一定会有收获,不敢说吊打面试官,至少跳槽面试,一旦涉及JVM知识,认真耐心看完全系列文章的同学,成功斩获offer几率一定会大幅提升。


    今天的主角调优监控命令,已经是非常贴合生产实战,现在打好基础,等系列第11篇,就开始针对实际案例,带大家应用工具命令解决实际问题。包含jps、jinfo、jstat、jstack、jmap、jhat命令应用示例,以及Arthas、GCeasy、MAT、GCViewer等工具应用介绍。

一、JDK自带工具命令

1.1 jps-查找JVM进程ID

     jps命令英文全称:java Virtual Machine Process Status Tool。

    查看jps命令可选参数有哪些,和shell命令一样,都是加-help 就可以看到参数列表。


jps :列出Java程序进程ID和Main函数名称

jps -q :只输出进程ID

jps -m :输出传递给JVM的参数

jps -l :输出main函数的完整路径

jps -v :显示传递给JVM的参数


    日常最常用就是,用jps -l、以及jps -v去查看jvm的进程ID,以及查看相关进程显示指定设置的jvm参数。


1.2 jinfo-查看并修改JVM运行参数

    jinfo英文全称:Java Configuration Info。

    jinfo可以用来查看正在运行的Java程序的扩展参数,甚至支持修改运行过程中的部分参数【对运维直接改线上服务比较友好】。比如:


jinfo可选参数:

-flag  打印指定J VM 参数

-flag [+|-] 打开或关闭JVM参数

-flag = 设置指定JVM参数值

-flags 打印JVM 参数


1.3 jstat-查看GC统计信息

    jstat命令英文全称:JVM Statistics Monitoring Tool。

    jstat可以查看Java程序运行时堆信息的相关情况。

jstat 主要参数如下:

-gc:显示与GC相关信息

-gccapacity:显示各个代的容量和使用情况

-gcnew:显示新生代信息

-gcnewcapacity:显示新生代大小和使用情况

-gcold:显示老年代信息

-gcoldcapacity:显示老年代大小

-gcutil:显示垃圾收集信息

-gccause:显示垃圾收集相关信息(同-gcutil),同时显示最后一次或当前正在发生的垃圾收集的诱发原因

-class:显示ClassLoader的相关信息

-compiler:显示JIT编译的相关信息


1.3.1 jstat -gc 采样GC情况

     我们通过-gc命令,可以轻松查看jvm进程当前内存区域使用情况,以及GC详细信息。比如:

# 进程ID 是8 ,采样间隔2s,采样数3
jstat -gc 8 2000 3


jstat gc各个输出字段含义:

S0C:年轻代中S0区的容量 (单位kb)

S1C:年轻代中S1区的容量 (单位kb)

S0U :年轻代中S0区目前已使用空间 (单位kb)

S1U :年轻代中S1区目前已使用空间 (单位kb)

EC :年轻代中Eden的容量 (单位kb)

EU :年轻代中Eden目前已使用空间 (单位kb)

OC :Old代的容量 (单位kb)

OU :Old代目前已使用空间 (单位kb)

MC:metaspace的容量 (单位kb)

MU:metaspace目前已使用空间 (单位kb)

CCSC:压缩类空间大小

CCSU:压缩类空间使用大小

YGC :从JVM启动到采样时年轻代中gc次数

YGCT :从JVM启动到采样时年轻代中gc所用时间(s)

FGC :从JVM启动到采样时old代(全gc)gc次数

FGCT :从JVM启动到采样时old代(全gc)gc所用时间(s)

GCT:从JVM启动到采样时gc用的总时间(s)


如果要单独查看老年代GC情况,可以通过-gcold来查询,比如:

# 进程ID 是8 ,采样间隔2s,采样数3
jstat -gcold 8 2s 3

单独查看老年代GC情况。


1.3.2 jstat -gcutil 查看gc统计信息

# 进程ID 是8 ,采样间隔2s,采样数3
jstat -gcutil 8 2s 3


输出各个字段含义:

S0 年轻代中S0区已使用的占当前容量百分比

S1 年轻代中S1区已使用的占当前容量百分比

E 年轻代中Eden已使用的占当前容量百分比

O 老年代已使用的占当前容量百分比

M metaspace已使用的占当前容量百分比

CCS 压缩使用比例

YGC 从JVM启动到采样时年轻代中gc次数

YGCT 从JVM启动到采样时年轻代中gc所用时间(s)

FGC 从JVM启动到采样时old代(全gc)gc次数

FGCT 从JVM启动到采样时old代(全gc)gc所用时间(s)

GCT 从JVM启动到采样时gc用的总时间(s)

1.4 jstack-线程死锁检测、接口卡顿问题排查

   jstack英文全称:Java Stack Trace。

   jstack可以很方便查看JVM里当前运行的线程信息,以及生成线程堆栈快照,用于分析是否有死锁、线程执行情况、接口卡顿等问题。

jstack 常用参数:

jstack [ option ] pid 查看指定JVM进程的线程堆栈信息。

jstack [ option ] pid > 文件 将指定进程线程栈信息dump出来写入到指定文件中。

1.4.1 查看JVM进程线程栈信息

     通过jstack pid命令,查看某个JVM进程当前运行线程栈全部信息。


也可以通过>指定对应文件,把线程栈信息先导出文件,然后拿出来分析。


1.4.2 查看当前全部线程状态-排查是否有死锁

    通过jstack -l 进程pid | grep 来过滤筛查线程栈信息,轻松查看所有线程状态,重点关注DeadLock死锁,Blocked等待阻塞状态。比如:

jstack -l 8 | grep 'java.lang.Thread.State'


1.5 jmap-把堆内存dump出来分析

    jmap英文全称:Java Virtual Machine Memory Map。

    jmap用来查看并导出堆内存状况,最好是结合jhat使用,jhat有可视化工具分析很方便。

1.5.1 jmap -heap 查看堆内存信息

     jmap -heap -pid 查看堆内存信息。比如最大堆内存,年轻代,老年代,元数据区大小,还有年轻代代的E,S区使用情况。



1.5.2 jmap -dump 导出堆内存信息

      通过 -dump参数可以生成堆快照文件,并可以指定以二进制格式。甚至可以指定了live子选项,让堆中只有活动的对象dump出来。堆文件可以通过 jjhat 可视化读取,jhat里具体说,也可以使用MAT等第三方工具分析。

这里必须注意:执行这个命令,应用会暂停执行。所以如果当前堆内存使用比较大,就会导致这个过程比较耗时,请慎用。

命令jmap -dump:format=b,file=myapp-heapdump.hprof 进程pid


1.5.3 jmap -clsstats 查看类加载器信息

比如:

jmap -clstats 8

这个命令执行统计会比较慢。


1.6 jhat 洞悉jvm head堆内存信息

    jhat 英文全称:Java Heap Analysis Tool。jhat 命令主要是可以启动一个 web服务,用来可视化分析Java head dump 出来的二进制文件。

   Java生成堆文件,可以用1.5 分享使用 jmap -dump 命令获取堆内存信息,以及我们在系统服务启动时候增加-XX:+HeapDumpOnOutOfMemoryError 参数,在发生OOM后,JVM自动dump出当时堆内存数据。


1.6.1 jhat 直接分析具体堆文件

   首先,我们用jmap命令dump出堆内存文件。命令:

jmap -dump:format=b,file=myapp-heapdump.hprof 进程pid


    然后,应用jhat命令,启动对该hprof堆文件进行分析。

jhat xxx.hprof


jhat的console web地址是http://localhost:7000/,打开界面如下:

    在这个界面里,我们可以看到已经加载到堆内存的全部类信息,包含是哪个类加载器加载的,弱引用、静态数据、每个类的子类父类信息。

jhat 启动后 html 页面末尾的Other Queriers主要是指:

All classes including platform:当前堆内存中所有的类信息。

Show all members of the rootset :从根集里的全部对象。

Show instance counts for all classes (including platform/excluding platform):包括或者不包含jdk启动类的所有类实例。

Show heap histogram:堆实例的分布图表。

Show finalizer summary:Finalizer 摘要。

Execute Object Query Language (OQL) query: 支持对象查询语句(OQL)。


二、第三方工具

2.1 Arthas 主流JVM监控诊断利器

    arthas官网地址:https://arthas.aliyun.com/,arthas 通过远程连接或者在应用本地机器上,实时查看服务 load、内存、gc、线程的状态信息,并支持在不修改应用代码的情况下,对业务问题进行诊断,包括查看方法调用的出入参、异常,监测方法执行耗时,类加载信息等,大大提升线上问题排查效率。

2.1.1 启动Arthas诊断

    在官网下载Arthas到本地后,启动jvm服务后,再启动Arthas诊断进程:

java -jar arthas-boot.jar

然后选择对接JVM进程序号,回车。就可以开始对本jvm进行在线诊断。


2.1.2 查看 dashboard

然后输入dashboard,按回车/enter,会展示当前进程的信息,按ctrl+c可以中断执行。

2.1.3 thread -b查看阻塞线程信息

2.1.4 jad 反编译JVM.class代码

jad的好处在于可以确认线上系统运行的代码是否我们之前打包提交的代码。

2.1.5 watch 实时监控方法返回值等

这个不再赘述过多案例,官网给了非常详细的使用说明,此外还有实时修改logger日志级别、查看jvm信息、trace追踪方法调用耗时等。大家可以参考https://arthas.aliyun.com/doc/quick-start.html

2.2 GCeasy-GC日志分析

https://gceasy.io/,GC提供在线日志分析,而且免费的,里面有Machine Learning分析GC,但是收费。堆内存数据分析非常高效,几秒内帮你分析并给出GC 、JVM堆优化建议。


2.2.1 设置保存JVM GC日志文件

在JVM启动参数里,新增:

-XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:/Users/xxx/projectcode/java-home/myapp-gc.log

比如,我们这里制造一个OOM demo,启动参数为:

-Xms16m -Xmx16m -Xmn8m -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:/Users/xxxx/projectcode/java-home/myapp-gc.log。

OOM Demo代码:

public static void main(String[] args) throws InterruptedException {
    //循环,让堆内存发生GC
    while (true) {
        Demo002JvmShow show = new Demo002JvmShow();
        User user = new User("拉丁");
        show.paramInt = user.getAge();
    }
}

发生OOM:


2.2.2 将GC文件上传到GCEasy分析

    打开https://gceasy.io/,上传gc日志分析。

2.2.3 GC日志结果分析

   gceasy可以从gc日志找到你各个区的内存分配情况,还有GC统计信息,一目了然。


2.4 GCViewer GC日志分析

   GCViewer也是一款开源的GC日志分析工具。项目在 github上可以下载[https://github.com/chewiebug/GCViewer],可以非常直观地分析出有待调优改进地方。大家有空可以下载体验一下。


2.5 MAT 内存泄漏分析最佳工具

    MAT是Memory Analyzer tool的缩写,也是一个优秀的、功能丰富的可视化内存分析工具,尤其是内存泄露分析表现优异。减少内存消耗分析工具。用MAT主要用于:

1、分析内存泄露,找到无法被回收的垃圾对象。

2、分析OOM原因,是否内存分配不合理,还是其他原因;

3、分析线程栈,线程死锁、阻塞情况;

4、查看对象个数及对象内存占用。

    由于篇幅有限,这里不详细展开举例visualVM、GCViewer、MAT应用。主流重点还是应用Arthas、jdk命令就很够用。大家只需要找到一个自己最喜欢的工具和命令集去解决生产监控问题即可。工具不在多,喜欢好用就行。


推荐阅读:

1、JVM进阶调优系列(3)堆内存的对象什么时候被回收?

2、JVM进阶调优系列(2)字节面试:JVM内存区域怎么划分,分别有什么用?

3、JVM进阶调优系列(1)类加载器原理一文讲透

4、JAVA并发编程系列(13)Future、FutureTask异步小王子

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
|
12天前
|
监控 架构师 Java
JVM进阶调优系列(6)一文详解JVM参数与大厂实战调优模板推荐
本文详述了JVM参数的分类及使用方法,包括标准参数、非标准参数和不稳定参数的定义及其应用场景。特别介绍了JVM调优中的关键参数,如堆内存、垃圾回收器和GC日志等配置,并提供了大厂生产环境中常用的调优模板,帮助开发者优化Java应用程序的性能。
|
13天前
|
Java
JVM进阶调优系列(5)CMS回收器通俗演义一文讲透FullGC
本文介绍了JVM中CMS垃圾回收器对Full GC的优化,包括Stop the world的影响、Full GC触发条件、GC过程的四个阶段(初始标记、并发标记、重新标记、并发清理)及并发清理期间的Concurrent mode failure处理,并简述了GC roots的概念及其在GC中的作用。
|
16天前
|
存储 安全 Java
jvm 锁的 膨胀过程?锁内存怎么变化的
【10月更文挑战第3天】在Java虚拟机(JVM)中,`synchronized`关键字用于实现同步,确保多个线程在访问共享资源时的一致性和线程安全。JVM对`synchronized`进行了优化,以适应不同的竞争场景,这种优化主要体现在锁的膨胀过程,即从偏向锁到轻量级锁,再到重量级锁的转变。下面我们将详细介绍这一过程以及锁在内存中的变化。
29 4
|
3月前
|
Java Docker 索引
记录一次索引未建立、继而引发一系列的问题、包含索引创建失败、虚拟机中JVM虚拟机内存满的情况
这篇文章记录了作者在分布式微服务项目中遇到的一系列问题,起因是商品服务检索接口测试失败,原因是Elasticsearch索引未找到。文章详细描述了解决过程中遇到的几个关键问题:分词器的安装、Elasticsearch内存溢出的处理,以及最终成功创建`gulimall_product`索引的步骤。作者还分享了使用Postman测试接口的经历,并强调了问题解决过程中遇到的挑战和所花费的时间。
|
16天前
|
缓存 算法 Java
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS
这篇文章详细介绍了Java虚拟机(JVM)中的垃圾回收机制,包括垃圾的定义、垃圾回收算法、堆内存的逻辑分区、对象的内存分配和回收过程,以及不同垃圾回收器的工作原理和参数设置。
38 4
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS
|
19天前
|
存储 缓存 算法
JVM核心知识点整理(内存模型),收藏再看!
JVM核心知识点整理(内存模型),收藏再看!
JVM核心知识点整理(内存模型),收藏再看!
|
6天前
|
存储 算法 Java
聊聊jvm的内存结构, 以及各种结构的作用
【10月更文挑战第27天】JVM(Java虚拟机)的内存结构主要包括程序计数器、Java虚拟机栈、本地方法栈、Java堆、方法区和运行时常量池。各部分协同工作,为Java程序提供高效稳定的内存管理和运行环境,确保程序的正常执行、数据存储和资源利用。
26 10
|
6天前
|
存储 算法 Java
Java虚拟机(JVM)的内存管理与性能优化
本文深入探讨了Java虚拟机(JVM)的内存管理机制,包括堆、栈、方法区等关键区域的功能与作用。通过分析垃圾回收算法和调优策略,旨在帮助开发者理解如何有效提升Java应用的性能。文章采用通俗易懂的语言,结合具体实例,使读者能够轻松掌握复杂的内存管理概念,并应用于实际开发中。
|
15天前
|
存储 监控 算法
JVM调优深度剖析:内存模型、垃圾收集、工具与实战
【10月更文挑战第9天】在Java开发领域,Java虚拟机(JVM)的性能调优是构建高性能、高并发系统不可或缺的一部分。作为一名资深架构师,深入理解JVM的内存模型、垃圾收集机制、调优工具及其实现原理,对于提升系统的整体性能和稳定性至关重要。本文将深入探讨这些内容,并提供针对单机几十万并发系统的JVM调优策略和Java代码示例。
42 2
|
16天前
|
存储 Java
JVM知识体系学习四:排序规范(happens-before原则)、对象创建过程、对象的内存中存储布局、对象的大小、对象头内容、对象如何定位、对象如何分配
这篇文章详细地介绍了Java对象的创建过程、内存布局、对象头的MarkWord、对象的定位方式以及对象的分配策略,并深入探讨了happens-before原则以确保多线程环境下的正确同步。
34 0
JVM知识体系学习四:排序规范(happens-before原则)、对象创建过程、对象的内存中存储布局、对象的大小、对象头内容、对象如何定位、对象如何分配