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

本文涉及的产品
容器镜像服务 ACR,镜像仓库100个 不限时长
简介: 本文介绍了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日志并进行多维度分析。
相关文章
|
18天前
|
Arthas 监控 Java
JVM进阶调优系列(9)大厂面试官:内存溢出几种?能否现场演示一下?| 面试就那点事
本文介绍了JVM内存溢出(OOM)的四种类型:堆内存、栈内存、元数据区和直接内存溢出。每种类型通过示例代码演示了如何触发OOM,并分析了其原因。文章还提供了如何使用JVM命令工具(如jmap、jhat、GCeasy、Arthas等)分析和定位内存溢出问题的方法。最后,强调了合理设置JVM参数和及时回收内存的重要性。
|
16天前
|
监控 Java 编译器
Java虚拟机调优实战指南####
本文深入探讨了Java虚拟机(JVM)的调优策略,旨在帮助开发者和系统管理员通过具体、实用的技巧提升Java应用的性能与稳定性。不同于传统摘要的概括性描述,本文摘要将直接列出五大核心调优要点,为读者提供快速预览: 1. **初始堆内存设置**:合理配置-Xms和-Xmx参数,避免频繁的内存分配与回收。 2. **垃圾收集器选择**:根据应用特性选择合适的GC策略,如G1 GC、ZGC等。 3. **线程优化**:调整线程栈大小及并发线程数,平衡资源利用率与响应速度。 4. **JIT编译器优化**:利用-XX:CompileThreshold等参数优化即时编译性能。 5. **监控与诊断工
|
27天前
|
存储 监控 Java
JVM进阶调优系列(8)如何手把手,逐行教她看懂GC日志?| IT男的专属浪漫
本文介绍了如何通过JVM参数打印GC日志,并通过示例代码展示了频繁YGC和FGC的场景。文章首先讲解了常见的GC日志参数,如`-XX:+PrintGCDetails`、`-XX:+PrintGCDateStamps`等,然后通过具体的JVM参数和代码示例,模拟了不同内存分配情况下的GC行为。最后,详细解析了GC日志的内容,帮助读者理解GC的执行过程和GC处理机制。
|
2月前
|
监控 架构师 Java
JVM进阶调优系列(6)一文详解JVM参数与大厂实战调优模板推荐
本文详述了JVM参数的分类及使用方法,包括标准参数、非标准参数和不稳定参数的定义及其应用场景。特别介绍了JVM调优中的关键参数,如堆内存、垃圾回收器和GC日志等配置,并提供了大厂生产环境中常用的调优模板,帮助开发者优化Java应用程序的性能。
|
2月前
|
存储 安全 Java
jvm 锁的 膨胀过程?锁内存怎么变化的
【10月更文挑战第3天】在Java虚拟机(JVM)中,`synchronized`关键字用于实现同步,确保多个线程在访问共享资源时的一致性和线程安全。JVM对`synchronized`进行了优化,以适应不同的竞争场景,这种优化主要体现在锁的膨胀过程,即从偏向锁到轻量级锁,再到重量级锁的转变。下面我们将详细介绍这一过程以及锁在内存中的变化。
38 4
|
16天前
|
Java Linux Windows
JVM内存
首先JVM内存限制于实际的最大物理内存,假设物理内存无限大的话,JVM内存的最大值跟操作系统有很大的关系。简单的说就32位处理器虽然可控内存空间有4GB,但是具体的操作系统会给一个限制,这个限制一般是2GB-3GB(一般来说Windows系统下为1.5G-2G,Linux系统下为2G-3G),而64bit以上的处理器就不会有限制。
15 1
|
2月前
|
缓存 算法 Java
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS
这篇文章详细介绍了Java虚拟机(JVM)中的垃圾回收机制,包括垃圾的定义、垃圾回收算法、堆内存的逻辑分区、对象的内存分配和回收过程,以及不同垃圾回收器的工作原理和参数设置。
72 4
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS
|
2月前
|
存储 缓存 算法
JVM核心知识点整理(内存模型),收藏再看!
JVM核心知识点整理(内存模型),收藏再看!
JVM核心知识点整理(内存模型),收藏再看!
|
2月前
|
存储 算法 Java
聊聊jvm的内存结构, 以及各种结构的作用
【10月更文挑战第27天】JVM(Java虚拟机)的内存结构主要包括程序计数器、Java虚拟机栈、本地方法栈、Java堆、方法区和运行时常量池。各部分协同工作,为Java程序提供高效稳定的内存管理和运行环境,确保程序的正常执行、数据存储和资源利用。
50 10
|
2月前
|
存储 算法 Java
Java虚拟机(JVM)的内存管理与性能优化
本文深入探讨了Java虚拟机(JVM)的内存管理机制,包括堆、栈、方法区等关键区域的功能与作用。通过分析垃圾回收算法和调优策略,旨在帮助开发者理解如何有效提升Java应用的性能。文章采用通俗易懂的语言,结合具体实例,使读者能够轻松掌握复杂的内存管理概念,并应用于实际开发中。