线上服务异常的定位、处理与优化的探索 - 第四章 常用分析工具介绍与使用
常用分析工具介绍与使用
JVM内置指令
内置指令指的是“安装JDK后”可以直接使用的命令,在未集成可视化工具时也能进行JVM相关分析和优化。
- JPS
类似linux ps命令,只输出Java进程,过滤掉其他进程信息
# jps -m
# jps -l
# jps -mlv 显示非常详细的java进程信息,并带有JVM参数
- JSTAT
查看gc时的内存信息和所耗时间
# jstat -gc <pid> <间隔时间> 按KB显示
# jstat -gcutil <pid> <间隔时间> 按百分比显示
# jstat -gccapacity <pid> 堆内存统计与GC次数
- JSTACK
查看线程信息,一般用来快速定位高占CPU线程。
# jstack -l <pid> 查看活动线程
# jstack -l <pid> >>[文件名] 导出活动线程信息到指定文件
# jstack <pid> | grep <’线程ID’> 查看线程信息
- JMAP
查看堆信息或导出堆内存快照(二进制),导出的快照文件需传回本地再使用图形界面工具详细分析。
注意:JMAP可能引起持续FULL GC,造成程序短暂无响应,应避免在线上业务高峰期操作。
# jmap -heap <pid> 查看堆信息概要
# jmap -dump:format=b,file=[文件名称].hprof <pid> 导出可分析的JVM内存快照信息
左侧图中所示JVM概要信息和堆概要信息在第三章节已详细阐述,不再赘述。
- JINFO
查看JVM参数信息,以及对JVM动态设置一些参数(并非所有参数都能动态设置)
# jinfo <pid> 查看JVM参数设置的详细信息
# jinfo -flag +PrintGCDetails <pid> 动态设置JVM参数->添加GC打印日志
# jinfo -flag -PrintGCDetails <pid> 动态设置JVM参数->去掉GC打印日志
# jinfo -flag +PrintGC <pid> 动态设置JVM参数->添加GC打印日志
# jinfo -flag -PrintGC <pid> 动态设置JVM参数->去掉GC打印日志
JConsole
JConsole一个基于JMX的可视化的JVM监控、分析工具,同时提供本地监控和远程监控两种方式。使用JConsole可以清晰方便的监控、分析应用程序的堆内存、线程、死锁、CPU占用率、载入类等信息。
- 示例基于JBoss-7.2.0、CentOS7.4、E7-FSSC、JDK1.7、JConsole、远程连接进程方式。
- 本小节中为了启动JMX远程功能,需要修改部分应用的配置文件。调优结束后切记将这些配置文件还原,避免生产环境上出现其他问题。
远程连接配置
- 修改jboss-as-7.2.0.Final/bin/standalone.conf配置文件
开启JMX支持,同时配置JMX所需参数
JAVA_OPTS="$JAVA_OPTS -Djava.rmi.server.hostname=192.168.3.91"
JAVA_OPTS="$JAVA_OPTS -Dcom.sun.management.jmxremote.port=8950"
JAVA_OPTS="$JAVA_OPTS -Dcom.sun.management.jmxremote.authenticate=false"
JAVA_OPTS="$JAVA_OPTS -Dcom.sun.management.jmxremote.ssl=false"
JAVA_OPTS="$JAVA_OPTS -Djboss.modules.system.pkgs=org.jboss.byteman,org.jboss.logmanager -Djava.awt.headless=true"
JAVA_OPTS="$JAVA_OPTS -Djava.util.logging.manager=org.jboss.logmanager.LogManager"
JAVA_OPTS="$JAVA_OPTS -Xbootclasspath/p:$JBOSS_HOME/modules/system/layers/base/org/jboss/logmanager/main/jboss-logmanager-1.4.0.Final.jar"
- 修改jboss-as-7.2.0.Final/standalone/configuration/standalone.xml配置文件
修改Jboss日志管理器配置,避免与JMX日志管理冲突
- 启动JConsole
使用本地CMD启动连接远程Linux上的进程
# jconsole <ip>:<port>
提示连接失败时,请选择“不安全”方式连接(不安全指未开启SSL)。
功能与使用
概览界面可以直观看到当前监控的应用的堆内存、线程、载入类、CPU占用率等,所有数据均为实时加载变化。
内存页签中选择下拉列选查看新生代、老年代、永久代等实时堆内存信息。右下角绿色柱状图与之对应,鼠标滑过会有提示。点击右上角执行GC,会马上向JVM发出指令执行一次垃圾收集。同时左下角会累计记录GC的所耗时间,如图所示:
线程页签可以查看峰值最高活动线程以及当前活动线程。左下角记录当前存活的线程。当怀疑应用出现死锁时点击左下角按钮“检测死锁”,如果有死锁出现则会在右下方显示死锁线程的详细信息,可以准确定位死锁代码和位置。
类载入页签可以查看当前监控的JVM载入的类数量、以及卸载类的数量信息。
VM概要页面中可以查看当前监控的JVM参数的详细数据,相当于是对前面页签提供的数据给出一个总结
VisualVM
VisualVM同样也是JDK自带的一款基于JMX的可视化工具。不仅提供了类似JConsole的功能,同时可以支持一键生成堆内存快照、线程快照,并支持使用插件添加更多扩展功能,可以认为是JConsole的加强版。
- 示例基于JBoss-7.2.0、CentOS7.4、E7-FSSC、JDK1.7、JConsole、远程连接进程方式。
- 本小节中为了启动JMX远程功能,需要修改部分应用的配置文件。调优结束后切记将这些配置文件还原,避免生产环境上出现其他问题。
远程连接配置
- 远程连接JBOSS启用JMX配置与上一章节(JConsole)一致,这里不再赘述。
打开jdk\bin目录下的jvisualvm.exe,选中左侧菜单“远程”,单机右键添加远程主机
选择刚才添加的主机,右键添加JMX连接(连接信息是JBOSS中所配置的JMX参数)。
功能与使用
概述界面描述了当前连接的主机所使用的JDK信息,以及JVM设置的参数信息。
监视页签中实施展示CPU、堆内存、永久代、载入类、线程等信息。右侧按钮“堆Dump”支持一键生成当前堆内存快照,类似JMAP功能。
导出Dump文件传回本地后,可以通过主菜单中的文件>装入后做具体数据分析。
线程页签中可以查看当前JVM的各种线程信息,包括:运行|休眠|等待。右侧线程Dump提供一键追踪和分析线程功能。
插件安装:选择工具>插件>设置>编辑,输入插件目录的URL地址。
URL查询地址:https://visualvm.github.io/pluginscenters.html,区分JDK版本。
MAT
Memory Analyzer Tool简称MAT,是一款基于Eclipse的堆内存快照分析工具,具有极其强大的分析功能!同时它也是一个上手容易深入了解很复杂的工具,官方使用文档多达数百页。MAT支持导入Dump文件分析,并自动生成问题报告,方便快速找到内存泄露或线程性能等问题。MAT支持OQL查询语言(类似SQL),使用OQL可以迅速查找想要看的内存内容。
www.eclipse.org/mat下载MAT,解压后即可使用。
功能与使用
在使用MAT之前首先需要拿到堆内存快照文件,4.1章节中有详细介绍这里不再赘述。
File>Open Heap Dump打开堆内存快照。
选择Leak Suspects Report,自动生成内存泄露嫌疑报告。
Actions>Histogram:列举内存中对象存在的个数和大小
选择一个可疑对象,右键MergeShortestPathsToGCRoots>excludeall phantom/weak/soft etc.references
逐步点开分析具体的泄露对象,注意:下方有对象总数:Total。
回到主页,点击Report>Leak Suspects
泄露报告中主要关注两点:
1:饼图深色部分是MAT分析后认为的可疑泄漏点。
2:每个泄漏点分别列出Problem Suspect和Details。
Problem Suspect 2所涉及到system class loader是类加载器正常执行现象,故排除。
Problem Suspect 1>See stacktrace查看线程堆栈跟踪分析
根据线程的追踪信息可以分析到内存泄露的具体代码的位置。
更多
关于MAT的功能和用法只做了简单的介绍,MAT是一个上手容易,深入了解很复杂的工具,使用MAT排查问题需要极强的耐心一步一步点下去深入分析。更多MAT功能请查阅官方文档深入了解:www.eclipse.org/mat/documentation
JProfiler
JProfiler是一款功能强大的性能采集剖析工具,提供可视化的操作界面,通常与性能压测类软件配合使用,也支持本地和远程服务端的连接方式。提供对SQL语句、线程、内存泄露、CPU使用率、执行类、执行方法等的监控和性能瓶颈的采集分析。
远程连接配置
- 示例基于JBoss-7.2.0、CentOS7.4、E7-FSSC、JDK1.7、JProfiler11、远程连接进程方式。
- 本小节中为了启动JProfiler远程功能,需要修改JBoss容器的启动脚本。使用结束后切记将启动文件还原,避免生产环境上出现其他问题。
- 远程连接成功的前提时需要本地端和远程端都安装同一大版本号的JProfile,否则会提示版本不一致无法连接。Linux下解压JProfile即可,无需添加环境变量。
正式调试之前我们首先需要使用JProfile的session功能为应用服务器启动脚本添加启动参数。Session>Integration Wizards>New Server Integration
选择容器以及版本(涵盖目前所有主流容器)
选择服务器操作系统以及处理器架构方式
选择JVM厂商:Oracle、IBM、J9……
选择JVM版本: 指服务器端的JVM版本
选择JDK所使用的虚拟机:如何查看所使用的虚拟机:java -version,下一步
选择连接方式,这里选择跟随容器服务立即启动监听,下一步
输入服务器上JProfile的安装路径,下一步
默认即可,下一步
这一步需要先将容器的启动脚本下载到本地,选择启动脚本,下一步
填写一个访问端口,缺省8849,下一步
选择稍后启动即可。至此,远程连接的配置部分结束了。在第8步配置时我们选择了一个启动脚本,同时JProfile也为我们生成了一个全新的启动脚本:standalone_jprofiler.sh。
编辑此脚本,确保JProfile参数的位置在standalone.conf配置下方,否则JVM将采用默认的永久代参数启动脚本,导致堆内存溢出PermGen Space。
改前:
改后:
最后将standalone_jprofiler.sh上传到JBoss启动脚本目录下,使用该脚本启动应用即可。
功能与使用
Session>Start Center,选择上一步所配置的连接
选择Sampling(Recommended)采样模式,下一步默认即可。
首页Overview视图展示了内存、GC、加载Class数、线程、CPU使用率等实时监控信息,还可以通过左侧菜单选择子视图查看具体分类信息的实时采集数据。
CPU views是一个比较常用的性能分析功能,此视图展示了应用中各方法的执行次数、执行时间、调用关系等信息,对定位和分析应用性能有绝佳的帮助。
CPU views>Call Tree通过树形图清晰地展现了方法间的层次调用关系。同时按照方法的执行总时间由大到小排序,简明清晰的展示所有服务端的请求。
CPU views>Hot Spots视图展示方法的单独执行时间、总执行时间、平均执行时间、调用次数等。
CPU views>Call Graph,选定Hot Spots视图中方法后右键选择Show Call Graph展示出与该方法直接关联的所有方法的关系图。
Databases同样是一个比较常用的性能分析功能,一般用来分析SQL执行的慢查询。
Databases>JDBC>Connections视图显示当前JDBC连接数量。
Databases>JDBC>Hot Spots视图展示了当前所采集到的SQL语句以及执行消耗的时间。
选定一条SQL,右键Show Node Details,可以查看该SQL的具体内容。
更多
- 官网地址下载:https://www.ej-technologies.com/download/jprofiler/files。
- 官方帮助文档:https://www.ej-technologies.com/resources/jprofiler/help/doc/main/introduction.html#jprofiler.introduction
Arthas
Arthas是Alibaba开源的Java诊断工具,采用命令行的交互模式使用,具有极其强大的线上服务诊断、监控、热部署功能,被广泛应用于IT企业。
安装与启动
安装Arthas
# curl -O https://arthas.gitee.io/arthas-boot.jar
安装命令执行后,会在当前位置下载Arthas程序
启动Arthas
# java -jar arthas-boot.jar 直接启动
# java -jar arthas-boot.jar --target-ip 192.168.3.91 绑定IP形式支持web console形式访问,默认端口8563.
启动之后自动加载所有java进程,输入进程编号后真正进入工作模式(挂在到相应的进程上)
常用命令
使用详解
- 示例基于JBoss-7.2.0、CentOS7.4、E7-FSSC、JDK1.7、Arthas3.2.0。
- 本小节中为了介绍Arthas常用命令如何使用启动了Arthas,生产环境下使用结束后一定记得关闭Arthas进程,一是避免过多资源消耗,二是Art。
- 仅选取使用频次较高的命令讲解。
dashboard命令可以查看当前系统的实时数据面板
ID: 线程ID,这个ID不是jstack中的ID,此ID用于Arthas的thread命令使用
NAME: 线程名
GROUP: 线程组名
PRIORITY: 线程优先级1~10之间,数字越大表示优先级越高
STATE: 线程的状态
CPU%: 线程消耗的cpu占比,采样100ms
TIME: 线程运行总时间,数据格式为{分:秒}
DAEMON: 是否是daemon线程
thread命令可以查看线程的信息和堆栈数据
thread 显示所有线程的信息
thread id 显示指定线程ID的堆栈信息(此ID为dashboard中的id)
thread -b 找出当前阻塞其他线程的线程
thread -n N 当前最忙的前N个线程并打印堆栈
thread --state <状态> 查看指定状态的线程(NEW/RUNNABLE/BLOCKED/WAITING/TIMED_WAITING/TERMINATED)
vmoption 命令可以查看、更新JVM诊断相关的参数(并非所有JVM参数都支持热更新)
vmoption 显示JVM参数和状态
vmoption PrintGCDetails true 更新指定参数的值(示例命令为开启GC详细日志)
jad 命令可以反编译指定已加载类的源码,通常用于查看源码是否存在打包未更新,以及与redefine一起用于热更新操作
jad com.epoch.customizeproject.xx.utils.XxUtil 反编译类
jad com.epoch.customizeproject.xx.utils.XxUtil callExecuteSql 反编译指定函数
watch 命令用于方法执行数据的观察:入参、返回值、异常等
watch <类名表达式> <方法名表达式> <观察表达式> <条件表达式>
watch com.xx.xx methodXX “{params,returnObj}” -x 3 (“”中间的都是ognl表达式)
-x 指定输出结果的属性遍历深度,默认为 1
-b 在方法调用之前观察
-s 在方法返回之后观察
-e 在方法异常之后观察
-f 在方法结束之后(正常返回和异常返回)观察
-E 开启正则表达式匹配,默认为通配符匹配
redefine 命令用于替换Class(热更新),一般结合jad、mc等命令使用
redefine /usr/app/LoginAction.class(修改后的Class文件位置)
redefine 后的Class不能使用reset还原
redefine 后的Class,再使用watch/jad/trace/tt/等命令会将修改后的字节码重置
redefine 的Class不能增加field/method,只能修改现有函数,同时正在运行的函数需等到执行完毕才能替换成功
trace 命令用于观察方法内部调用路径,以及方法路径上的每个节点上耗时
trace com.xx.xx methodXX 捕获指定类指定方法的调用路径
trace com.xx.xx methodXX '#cost > 100' 在调用路径中只捕获执行时间超过100ms的结果
trace -E com.xx.ClassA|com.xx.ClassB method1|method2|method3支持正则表达式,可以同时监控多个类的多个方法的调用路径
ognl 命令用于执行ognl表达式:loader/clazz/method/target/params/returnObj/throwExp/isBefore/isThrow/isReturn
ognl的特殊用法请参考:https://github.com/alibaba/arthas/issues/71
ognl的表达式官方指南:https://commons.apache.org/proper/commons-ognl/language-guide.html
tt 命令作用类似于watch命令,watch是一次性的,tt能够保存下来,方便后续持续分析,重新调用,还原当时的情况等。
tt -t com.xx.xx methodXX 记录调用
tt -t com.xx.xx methodXX -n 5 记录调用5次后即退出命令(避免JVM内存撑爆)
tt -l 展示所有捕获的记录
tt -s 'method.name=="methodXX"' 从记录中筛选出方法名为methodXX的记录
tt -i index 查看指定编号的调用信息,index是tt列表中的编号
tt -i index -x 2 同上,所记录的参数向下展开2层明细信息
tt -i index -p 通过所记录的调用信息,重新调用一次,相当于还原当时的情况
tt命令是将当前环境的对象引用保存起来,如果方法内部对入参进行了变更,或者返回的对象经过了后续的处理,那么在 tt 查看的时候将无法看到当时最准确的值,此情况请移步watch实时命令跟踪。
profiler 命令用于生成应用热点的火焰图。
profiler start 启动采集数据
profiler getSamples 获取已采集的sample的数量
profiler status 查看采集状态
profiler stop 停止采集数据
profiler stop --file /usr/app/arthas/20200502-2257.svg 指定火焰图保存目录
profiler stop --format html 指定生成火焰图格式
通过web console->Arthas Output可以直接打开已经生成的火焰图文件,图中信息支持下钻。
更多
- 如果条件允许建议尽量避开应用的高峰期使用Arthas排查问题,Arthas有可能拖慢应用速度(一些的监控、加载、观测、录制命令等)。
- 章节4.6.3未详尽所有Arthas命令,更多命令与教程请查阅官方文档:https://arthas.gitee.io/index.html
- 一张图掌握Arthas命令:https://gitee.com/arthas/arthas/issues/I180P1
- 用户案例:https://github.com/alibaba/arthas/issues?q=label%3Auser-case
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?