Arthas在线诊断工具使用

Arthas 命令

 

下载地址

下载地址:Releases · alibaba/arthas · GitHub

参考官方文档:https://arthas.aliyun.com/doc/quick-start.html

使用版本arthas-all-3.6.0版本,windows环境下使用

解压到指定目录 /xx/xx/arthas/

详情如下图

启动Arthas

Windows 控制台 cmd

cd /xx/xx/arthas/

启动命令 java  -jar arthas-boot.jar

启动后如下图

蓝色方框表示java进程下标,输入下游即可进入相关java进程

如下图

红色方框表示 java 进程ID,如上图

默认30分钟后会自动退出session

常用命令及操作

dashboard-查看进程面板

memory-查看内存使用情况

jvm-查看JVM使用情况

MACHINE-NAME

机器名称

JVM-START-TIME

JVM开始时间

MANAGEMENT-SPEC-VERSION

管理规范版本

SPEC-NAME

规范名称

SPEC-VENDOR

规范供应商

SPEC-VERSION

规范版本

VM-NAME

虚机供应商

VM-VENDOR

虚机供应商

VM-VERSION

虚机版本

INPUT-ARGUMENTS

输入编码

CLASS-PATH

CLASS路径

BOOT-CLASS-PATH

引导类路径

LIBRARY-PATH

Jar库路径

CLASS-LOADING

类加载

LOADED-CLASS-COUNT

加载类计数

TOTAL-LOADED-CLASS-COUNT

总加载类计数

UNLOADED-CLASS-COUNT

未加载类计数

IS-VERBOSE

是否详细

GARBAGE-COLLECTORS

垃圾回收器

PS Scavenge

PS清除

PS MarkSweep

PS 标记清除

MEMORY-MANAGERS

内存管理器

CodeCacheManager

代码缓存管理器

Metaspace Manager

元空间管理器

HEAP-MEMORY-USAGE

堆内存使用情况

NO-HEAP-MEMORY-USAGE

非堆内存使用情况

PENDING-FINALIZE-COUNT

等待完成数

OPERATING-SYSTEM

操作系统

THREAD -> COUNT

JVM当前活跃的线程数

THREAD -> DAEMON-COUNT

JVM当前活跃的守护线程数

THREAD -> PEAK-COUNT

从JVM启动开始曾经活着的最大线程数

THREAD -> STARTED-COUNT

从JVM启动开始总共启动过的线程次数

THREAD -> DEADLOCK-COUNT

JVM当前死锁的线程数

FILE-DESCRIPTOR

文件描述符

MAX-FILE-DESCRIPTOR-COUNT

JVM进程最大可以打开的文件描述符数

OPEN-FILE-DESCRIPTOR-COUNT

JVM当前打开的文件描述符数

sysprop-查看,修改系统参数

sun.desktop                    

awt.toolkit                    

file.encoding.pkg              

java.specification.version     

sun.cpu.isalist                

sun.jnu.encoding               

java.class.path                

java.vm.vendor                  

sun.arch.data.model            

user.variant                   

java.vendor.url                

user.timezone                  

os.name                        

java.vm.specification.version  

user.country                   

sun.java.launcher              

sun.boot.library.path          

sun.java.command               

sun.cpu.endian                 

user.home                      

user.language                  

java.specification.vendor      

java.home                      

file.separator                 

line.separator                                          

java.vm.specification.vendor   

java.specification.name        

java.awt.graphicsenv           

sun.boot.class.path             

user.script                    

sun.management.compiler        

java.runtime.version           

user.name                      

path.separator                 

os.version                      

java.endorsed.dirs             

java.runtime.name              

file.encoding                  

java.vm.name                   

java.vendor.url.bug            

java.io.tmpdir                 

java.version                   

user.dir                        

os.arch                        

java.vm.specification.name     

java.awt.printerjob            

sun.os.patch.level             

java.library.path              

java.vm.info                   

java.vendor                    

java.vm.version                

java.ext.dirs                  

sun.io.unicode.encoding        

java.class.version             

sysprop查看所有系统属性

sysprop key 查看单个系统属性

sysprop key value 修改单个系统属性

sysenv-查看当前JVM的环境属性

sysenv 查看所有jvm环境变量

sysenv key  查看单个jvm环境变量

vmoption 查看,更新jvm参数

HeapDumpBeforeFullGC                

HeapDumpAfterFullGC                 

HeapDumpOnOutOfMemoryError          

HeapDumpPath                        

CMSAbortablePrecleanWaitMillis      

CMSWaitDuration                     

CMSTriggerInterval                  

PrintGC                             

PrintGCDetails                      

PrintGCDateStamps                   

PrintGCTimeStamps                    

PrintGCID                           

PrintClassHistogramBeforeFullGC     

PrintClassHistogramAfterFullGC      

PrintClassHistogram                 

MinHeapFreeRatio                    

MaxHeapFreeRatio                    

PrintConcurrentLocks                

UnlockCommercialFeatures

在FullGC前生产dump文件

在FullGC后生产dump文件

在oom异常时生成dump文件

指定dump文件路径

CMS可采用预清除等待时间毫秒

CMS间隙等待时间

CMS 触发间隔

打印GC日志

打印GC详情

打印GC日志时间戳

打印此次垃圾回收距离jvm开始运行的所耗时间

打印GCID

在FullGC前将内存中的对象以日志的形式输出

在FullGC后将内存中的对象以日志的形式输出

遇到 Ctrl-Break 后打印类实例的柱状信息

空闲堆空间最小占比

空闲堆空间最大占比

遇到Ctrl-Break后打印并发锁的相关信息

解锁商业功能

vmoption 查看所有JVM参数

vmoption key 查看单个jvm参数

vmoption key value 修改jvm属性信息

classLoader 查看classloader的继承树,urls,类加载信息

classLoader -l 查看类加载实例统计数据

classLoader -t 查看类加载器树形结构

classLoader -c hashcode  查看加载器加载jar的urls

                                             

jad 反编译指定已加载类的源码

jad  .class  查看反编译源码,包含classLoader,重新编译.class

jad --source-only .class 查看只源码不显示classLoader

jad --source-only .class method --lineNumber false

查看某方法源码不显示行号

sc 查看jvm类加载信息

sc   -d  class 查看类属性信息

下图红框为类加载器

sc  -d  -f  class 查看类信息,属性信息

sc  -d  class |grep key 查看某个类属性信息

mc 将.java文件编译成 .class 文件

mc  xxx.java  -d  path 指定文件编译保存地址

mc  -c hashcode xxx.java  -d path 指定类加载器编译

retransform 加载外部的.class文件,覆盖jvm已加载的类

retransform path 指定重新加载外部.class文件

retransform的限制

  1. 不允许新增加field/method
  2. 正在跑的函数,没有退出不能生效,如下图mian()不生效,test()生效
  3. 重复多次加载同一个 .class 文件 id最大生效

retransform -l 统计所有重新加载 .class文件

retransform -d id编号 删除重载的.class文件  -d ID编号 retransform --deleteAll 删除全部

retransform --classPattern   xxx.class 文件 重新回复编译文件

watch java方法执行数据观测

注:

观察表达式, 返回时的  {参数,  this对象, 返回值}

观察表达式,默认值是{params, target, returnObj}

-x 查看层级,-n 查看次数

watch  class  method  实时查看指定类的方法入参和出参,持续打印结果

实时查看耗时大于10毫秒数据,查看一次展示5层级参数

watch class method  "{params,returnObj,throwExp}" '#cost>10' -x 5 -n 1
实时查看耗时大于10毫秒且第一个数据等于1的数据,查看一次展示5层级参数
watch class method  "{params,returnObj,throwExp}" '#cost>10 && params[0]==1'  -x 5 -n 1
实时查看第一个数据大于1且第二个数据等于“hello”的数据,查看一次展示5层级参数
watch class method  "{params,returnObj,throwExp}" 'params[0]>1 && params[1]=="hello"' -x 5 -n 1
实时查看第一个数据小于5或者 第二个数据等于“world”的数据,查看一次展示5层级参数
watch *.CommonTest test "{params,returnObj,throwExp}" 'params[0]<5 || params[1]=="wolrd"' -x 5 -n 1

trace 方法内部调用路径及耗时

trace   class   method 查看指定类调用链及耗时

ts=2022-04-22 15:24:01; 系统执行时间

thread_name=main;id=1; 线程名称,线程ID

is_daemon=false;priority=5; 是否守护线程,权重

TCCL=sun.misc.Launcher$AppClassLoader@18b4aac2 类加载器

`---[0.1172ms] fills.arthas.ArthasTest:test() 执行时间

stack 输出当前方法被调用的调用路径

stack   class   method 查看指定类方法所有调用路径

ts=2022-04-22 15:37:02; 系统执行时间

thread_name=main;id=1; 线程名称,线程ID

is_daemon=false;priority=5; 是否守护线程,权重

TCCL=sun.misc.Launcher$AppClassLoader@18b4aac2 类加载器

@fills.arthas.ArthasTest.test()

        at fills.arthas.ArthasTest.main(ArthasTest.java:9)  调用链

ognl 调用静态属性和方法

1.查看静态属性

ognl  ‘@全路经类名@属性字段’  -x 1 查看字段一级属性值

2.查看静态方法

ognl  ‘@全路经类名@方法名称(xx,xx)’  -x  1 调用静态方法查看一级返回值; 2,3查看二,三级参数

案例场景应用

调用链接口新性能损耗分析

trace  class  method 实时抓取调用类方法请求及调用链处理时耗

trace 每次只能查看一级链路耗时情况

trace  com.ddky.top.meituan.web.controller.product.ProductManageController

listProductMapping

从调用链耗时情况可以看出是在调用dubbo服务耗时最多

 +---[227.5465ms] com.ddky.top.meituan.service.ProductManageService:listProductManage() #140

trace com.ddky.top.meituan.service.ProductManageService listProductManage

 +---[19.0228ms] com.ddky.top.meituan.data.dao.ProductManageDao:countProductMapping() #128

 +---[9.3109ms] com.ddky.top.meituan.data.dao.ProductManageDao:listProductMapping() #132

+---[79.1293ms] com.ddky.top.inner.api.service.InnerProductClient:getPageFromCondition() #167

调用外部dubbo耗时

+---[63.7842ms] com.ddky.top.meituan.service.ProductPriceService:newReadBatchGetTopPrice() #171

循环内部接口调用耗时

从上图看出主要耗时地方有2处

建议优化方案

调用外部dubbo接口异步处理

调用内部循环调用改为批量查询

在线修改源码并热发布迅速解决线上问题

原有逻辑操作

  1. jad  --source-only  .class  --lineNumber false  >  xxx.java  打印源码到指定文件
  2. vi xxx.java 修改源码
  3. sc  .class  |grep classLoaderHash  查看源码类加载器hashcode
  4. mc  -c hashcode  .java  -d path  生成新的.class 文件

注(1-4步)可以线下生成class文件上传线上服务器,复杂的类编译很容易出错,不建议

     5.retransform  class  重新加载类文件

     6.jad  class 或者 retransform --classPattern class 重新加载源class文件复原线上环境

在线查看修改静态方法及属性值

1.查看线上静态配置属性

ognl  ‘@全路经类名@属性字段’  -x 1 查看字段一级属性值

2.调用线上静态方法

ognl  ‘@全路经类名@方法名称(xx,xx)’  -x  1 调用静态方法查看一级返回值

3.修改静态属性变量

ognl  ‘@全路经类名@方法名称(xxx)’   注: 该方法内部未修改属性

修改日志等级

1.logger --name ROOT --level debug  修改日志等级为debug

2. logger -c 2a139a55 --name ROOT --level debug  指定classloader更新日志等级为debug

还有其他运维场景比如修改jvm,系统环境参数,查看线上线程内存使用情况

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值