Arthas - 开源 Java 诊断工具

转载自  Arthas使用

Authas — 开源的java诊断工具

下载安装

authas是一个jar包,可以直接下载后运行

wget https://alibaba.github.io/arthas/arthas-boot.jarjava -jar arthas-boot.jar

就可以启动起来。启动后,authas会自动检测存在的java进程,这时候需要选择你想要诊断的进程,回车即可。如下图所示:

 

如果不知道某个java进程的详情,可以使用

jps -mlVv
或
ps -ef| grep java

来查看.

 

常用命令

基础命令

help——查看命令帮助信息
cat——打印文件内容,和linux里的cat命令类似
pwd——返回当前的工作目录,和linux命令类似
cls——清空当前屏幕区域
session——查看当前会话的信息
reset——重置增强类,将被 Arthas 增强过的类全部还原,Arthas 服务端关闭时会重置所有增强过的类
version——输出当前目标 Java 进程所加载的 Arthas 版本号
history——打印命令历史
quit——退出当前 Arthas 客户端,其他 Arthas 客户端不受影响
shutdown——关闭 Arthas 服务端,所有 Arthas 客户端全部退出
keymap——Arthas快捷键列表及自定义快捷键

JVM相关

Dashboard

dashboardUSAGE:dashboard [-b] [-i <value>] [-n <value>]SUMMARY:Overview of target jvm's thread, memory, gc, vm, tomcat info.EXAMPLES:dashboarddashboard -n 10dashboard -i 2000WIKI:https://alibaba.github.io/arthas/dashboardOPTIONS:-b, --batch                                   Execute this command in batch mode.-i, --interval <value>                        The interval (in ms) between two executions, default is 5000 ms.-n, --number-of-execution <value>             The number of times this command will be executed.

 

可以看到,这里会显示出线程(按照cpu占用百分比倒排)、内存(堆空间实时情况)、GC情况等数据。

常用的参数:

-i 400ms 每次执行间隔时间

-n 执行多少次dashboard,不指定的话会一直刷新

thread

thread命令用来查看当前jvm中的线程信息的,如下图所示:

 

 

可以看到,默认执行thread命令,会直接打印出当前所有的线程。

$ threadUSAGE:thread [-b] [-i <value>] [-n <value>] [id]SUMMARY:Display thread info, thread stackEXAMPLES:threadthread 51thread -n -1thread -n 5thread -bthread -i 2000WIKI:https://alibaba.github.io/arthas/threadOPTIONS:-b, --include-blocking-th  Find the thread who is holding a lock that blocks tread                       he most number of threads.-i, --sample-interval <va  Specify the sampling interval (in ms) when calculatlue>                       ing cpu usage.-n, --top-n-threads <valu  The number of thread(s) to show, ordered by cpu utie>                         lization, -1 to show all.<id>                       Show thread stack

常用参数:

-b 查看目前block的线程

-i 5000ms 查看在接下来的多长时间内 统计cpu利用率

-n 5 查看cpu占用率前5的线程的堆栈信息

<thread_id> 直接跟着线程id,可以看到thread的堆栈信息

如下:

$ thread -n 1
"as-command-execute-daemon" Id=396 cpuUsage=53% RUNNABLEat sun.management.ThreadImpl.dumpThreads0(Native Method)at sun.management.ThreadImpl.getThreadInfo(ThreadImpl.java:448)at com.taobao.arthas.core.command.monitor200.ThreadCommand.processTopBusyThreads(ThreadCommand.java:133)at com.taobao.arthas.core.command.monitor200.ThreadCommand.process(ThreadCommand.java:79)at com.taobao.arthas.core.shell.command.impl.AnnotatedCommandImpl.process(AnnotatedCommandImpl.java:82)at com.taobao.arthas.core.shell.command.impl.AnnotatedCommandImpl.access$100(AnnotatedCommandImpl.java:18)at com.taobao.arthas.core.shell.command.impl.AnnotatedCommandImpl$ProcessHandler.handle(AnnotatedCommandImpl.java:111)at com.taobao.arthas.core.shell.command.impl.AnnotatedCommandImpl$ProcessHandler.handle(AnnotatedCommandImpl.java:108)at com.taobao.arthas.core.shell.system.impl.ProcessImpl$CommandProcessTask.run(ProcessImpl.java:370)at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)at java.lang.Thread.run(Thread.java:748)Number of locked synchronizers = 1- java.util.concurrent.ThreadPoolExecutor$Worker@21b51d37Affect(row-cnt:0) cost in 541 ms.

可以看到这里占用cpu最高的一个线程的栈信息。

jvm

查看当前jvm信息

sysprop

查看和修改JVM的系统属性

sysenv

查看JVM的环境变量

getstatic

查看类的静态属性

class/classloader相关

mc

Memory Compiler/内存编译器,编译.java文件生成.class

mc /tmp/Test.java

redefine

加载外部的.class文件,redefine jvm已加载的类。

redefine /tmp/Test.class
redefine -c 327a647b /tmp/Test.class /tmp/Test\$Inner.class

sc

Search class

查看jvm中已加载的类,不过直接执行sc并没有太多信息,如下:

$ sc com.google.common.hash.HashFunction
com.google.common.hash.AbstractHashFunction
com.google.common.hash.HashFunction
com.google.common.hash.MessageDigestHashFunction
Affect(row-cnt:3) cost in 213 ms.

需要加入-d参数,如下

$ sc -d com.google.common.hash.HashFunctionclass-info        com.google.common.hash.AbstractHashFunctioncode-sourcename              com.google.common.hash.AbstractHashFunctionisInterface       falseisAnnotation      falseisEnum            falseisAnonymousClass  falseisArray           falseisLocalClass      falseisMemberClass     falseisPrimitive       falseisSynthetic       falsesimple-name       AbstractHashFunctionmodifier          abstractannotation        com.google.errorprone.annotations.Immutableinterfaces        com.google.common.hash.HashFunctionsuper-class       +-java.lang.Objectclass-loader      +-com.intellij.util.lang.UrlClassLoader@277050dcclassLoaderHash   277050dcclass-info        com.google.common.hash.HashFunctioncode-sourcename              com.google.common.hash.HashFunctionisInterface       trueisAnnotation      falseisEnum            falseisAnonymousClass  falseisArray           falseisLocalClass      falseisMemberClass     falseisPrimitive       falseisSynthetic       falsesimple-name       HashFunctionmodifier          abstract,interface,publicannotation        com.google.errorprone.annotations.Immutableinterfacessuper-classclass-loader      +-com.intellij.util.lang.UrlClassLoader@277050dcclassLoaderHash   277050dcclass-info        com.google.common.hash.MessageDigestHashFunctioncode-sourcename              com.google.common.hash.MessageDigestHashFunctionisInterface       falseisAnnotation      falseisEnum            falseisAnonymousClass  falseisArray           falseisLocalClass      falseisMemberClass     falseisPrimitive       falseisSynthetic       falsesimple-name       MessageDigestHashFunctionmodifier          finalannotation        com.google.errorprone.annotations.Immutableinterfaces        java.io.Serializablesuper-class       +-com.google.common.hash.AbstractHashFunction+-java.lang.Objectclass-loader      +-com.intellij.util.lang.UrlClassLoader@277050dcclassLoaderHash   277050dcAffect(row-cnt:3) cost in 102 ms.

可以看到这里有更详细的信息。

具体的参数如下:

$ help scUSAGE:sc [-d] [-x <value>] [-f] [-h] [-E] class-patternSUMMARY:Search all the classes loaded by JVMEXAMPLES:sc -d org.apache.commons.lang.StringUtilssc -d org/apache/commons/lang/StringUtilssc -d *StringUtilssc -d -f org.apache.commons.lang.StringUtilssc -E org\\.apache\\.commons\\.lang\\.StringUtilsWIKI:https://alibaba.github.io/arthas/scOPTIONS:-d, --details                                                       Display the details of class-x, --expand <value>                                                Expand level of object (0 by default)-f, --field                                                         Display all the member variables-h, --help                                                          this help-E, --regex                                                         Enable regular expression to match (wildcard matching by default)<class-pattern>                                                     Class name pattern, use either '.' or '/' as separator

sm

search method

$ sm xx.xxx.xx.xx.xxx.xx.CouponService
xx.xxx.xx.xx.xxx.xx.CouponServiceImpl <init>()V
xx.xxx.xx.xx.xxx.xx.CouponServiceImpl matchCouponOnShopIds(Ljava/lang/Long;Ljava/util/List;)Ljava/util/Map;
xx.xxx.xx.xx.xxx.xx.CouponServiceImpl$$EnhancerByGuice$$9b64c3b8 <init>()V
xx.xxx.xx.xx.xxx.xx.CouponServiceImpl$$EnhancerByGuice$$9b64c3b8 CGLIB$matchCouponOnShopIds$0(Ljava/lang/Long;Ljava/util/List;)Ljava/util/Map;
xx.xxx.xx.xx.xxx.xx.CouponServiceImpl$$EnhancerByGuice$$9b64c3b8 CGLIB$SET_THREAD_CALLBACKS([Lcom/google/inject/internal/cglib/pr$ oxy/$Callback;)V
xx.xxx.xx.xx.xxx.xx.CouponServiceImpl$$EnhancerByGuice$$9b64c3b8 CGLIB$SET_STATIC_CALLBACKS([Lcom/google/inject/internal/cglib/proxy/$Callback;)V
xx.xxx.xx.xx.xxx.xx.CouponServiceImpl$$EnhancerByGuice$$9b64c3b8 CGLIB$STATICHOOK35()V
xx.xxx.xx.xx.xxx.xx.CouponServiceImpl$$EnhancerByGuice$$9b64c3b8 CGLIB$BIND_CALLBACKS(Ljava/lang/Object;)V
xx.xxx.xx.xx.xxx.xx.CouponServiceImpl$$EnhancerByGuice$$9b64c3b8 CGLIB$findMethodProxy(Lcom/google/inject/internal/cglib/core/$Signature;)Lcom/google/inject/internal/cglib/proxy/$MethodProxy;
xx.xxx.xx.xx.xxx.xx.CouponServiceImpl$$EnhancerByGuice$$9b64c3b8 matchCouponOnShopIds(Ljava/lang/Long;Ljava/util/List;)Ljava/util/Map;
xx.xxx.xx.xx.xxx.xx.CouponService matchCouponOnShopIds(Ljava/lang/Long;Ljava/util/List;)Ljava/util/Map;
com.sun.proxy.$Proxy197 <init>(Ljava/lang/reflect/InvocationHandler;)V
com.sun.proxy.$Proxy197 matchCouponOnShopIds(Ljava/lang/Long;Ljava/util/List;)Ljava/util/Map;
com.sun.proxy.$Proxy197 equals(Ljava/lang/Object;)Z
com.sun.proxy.$Proxy197 toString()Ljava/lang/String;
com.sun.proxy.$Proxy197 hashCode()I
Affect(row-cnt:16) cost in 53 ms.

可以看到,通过sm命令可以查到对应类的所有方法

通过加入-d参数可以获取method的信息信息

$ sm xx.xxx.xx.xx.xxx.xx.CouponService -ddeclaring-class   xx.xxx.xx.xx.xxx.xx.CouponServiceImplconstructor-name  <init>modifier          publicannotationparametersexceptionsdeclaring-class  xx.xxx.xx.xx.xxx.xx.CouponServiceImplmethod-name      matchCouponOnShopIdsmodifier         publicannotationparameters       java.lang.Longjava.util.Listreturn           java.util.Mapexceptions       xx.xxx.xx.xx.xxx.xx.ServiceException...

sh

jad

反编译代码,如下

$ jad com.google.common.hash.HashFunctionClassLoader:
+-com.intellij.util.lang.UrlClassLoader@277050dcLocation:/** Decompiled with CFR 0_132.** Could not load the following classes:*  com.google.common.hash.Funnel*  com.google.common.hash.HashCode*  com.google.common.hash.Hasher*  com.google.errorprone.annotations.Immutable*/
package com.google.common.hash;import com.google.common.hash.Funnel;
import com.google.common.hash.HashCode;
import com.google.common.hash.Hasher;
import com.google.errorprone.annotations.Immutable;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;@Immutable
public interface HashFunction {public int bits();public HashCode hashLong(long var1);public HashCode hashInt(int var1);public <T> HashCode hashObject(T var1, Funnel<? super T> var2);public HashCode hashUnencodedChars(CharSequence var1);public HashCode hashString(CharSequence var1, Charset var2);public HashCode hashBytes(ByteBuffer var1);public HashCode hashBytes(byte[] var1, int var2, int var3);public HashCode hashBytes(byte[] var1);public Hasher newHasher();public Hasher newHasher(int var1);
}Affect(row-cnt:1) cost in 1730 ms.

classloader

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

 

查看其参数如下

$ help classloaderUSAGE:classloader [-a] [-c <value>] [-h] [-i] [-l] [--load <value>] [-r <value>] [-t]SUMMARY:Show classloader infoEXAMPLES:classloaderclassloader -tclassloader -lclassloader -c 327a647bclassloader -c 327a647b -r META-INF/MANIFEST.MFclassloader -aclassloader -a -c 327a647bclassloader -c 659e0bfd --load demo.MathGameWIKI:https://alibaba.github.io/arthas/classloaderOPTIONS:-a, --all                                                           Display all classes loaded by ClassLoader-c, --classloader <value>                                           The hash code of the special ClassLoader-h, --help                                                          this help-i, --include-reflection-classloader                                Include sun.reflect.DelegatingClassLoader-l, --list-classloader                                              Display statistics info by classloader instance--load <value>                                                  Use ClassLoader to load class, won't work without -c specified-r, --resource <value>                                              Use ClassLoader to find resources, won't work without -c specified-t, --tree                                                          Display ClassLoader tree

-t : 把classloader的树打印出来,也会打印出来粗略的hashcode

-l : 根据classloader实例的个数来打印classloader,会打印出来hashcode

-c : 用classloader对应的hashcode 来查看对应的jar urls

查看classloader tree信息

$ classloader -t
+-BootstrapClassLoader
+-sun.misc.Launcher$ExtClassLoader@6379eb+-com.taobao.arthas.agent.ArthasClassloader@5ab570f5+-sun.misc.Launcher$AppClassLoader@18b4aac2+-com.alibaba.fastjson.util.ASMClassLoader@34c3f8d2+-com.alibaba.fastjson.util.ASMClassLoader@463b35ac+-com.alibaba.jvm.sandbox.agent.SandboxClassLoader@567d299b+-ModuleClassLoader[crc32=3750510264;file=/data/.ewatch/ewatch-install/sandbox/lib/../module/sandbox-mgr-module.jar;]+-ModuleClassLoader[crc32=2030492332;file=/data/.ewatch/ewatch-install/sandbox/ewatch/ewatch-agent-jar-with-dependencies.jar;]+-com.alibaba.jvm.sandbox.core.classloader.ProviderClassLoader@42f93a98
Affect(row-cnt:10) cost in 20 ms.

查看URLClassLoader实际的urls

$ classloader -c 5ab570f5
file:/root/.arthas/lib/3.1.1/arthas/arthas-core.jarAffect(row-cnt:1790) cost in 19 ms.

使用ClassLoader去查找resource

$ classloader -c 3d4eac69  -r META-INF/MANIFEST.MFjar:file:/System/Library/Java/Extensions/MRJToolkit.jar!/META-INF/MANIFEST.MFjar:file:/private/tmp/arthas-demo.jar!/META-INF/MANIFEST.MFjar:file:/Users/hengyunabc/.arthas/lib/3.0.5/arthas/arthas-agent.jar!/META-INF/MANIFEST.MF

也可以尝试查找类的class文件:

$ classloader -c 1b6d3586 -r java/lang/String.classjar:file:/Library/Java/JavaVirtualMachines/jdk1.8.0_60.jdk/Contents/Home/jre/lib/rt.jar!/java/lang/String.class

使用ClassLoader去加载类

$ classloader -c 3d4eac69 --load demo.MathGame
load class success.class-info        demo.MathGamecode-source       /private/tmp/arthas-demo.jarname              demo.MathGameisInterface       falseisAnnotation      falseisEnum            falseisAnonymousClass  falseisArray           falseisLocalClass      falseisMemberClass     falseisPrimitive       falseisSynthetic       falsesimple-name       MathGamemodifier          publicannotationinterfacessuper-class       +-java.lang.Objectclass-loader      +-sun.misc.Launcher$AppClassLoader@3d4eac69+-sun.misc.Launcher$ExtClassLoader@66350f69classLoaderHash   3d4eac69

monitor/watch/trace相关

monitor

对匹配 class-patternmethod-pattern的类、方法的调用进行监控。

monitor 命令是一个非实时返回命令.

实时返回命令是输入之后立即返回,而非实时返回的命令,则是不断的等待目标 Java 进程返回信息,直到用户输入 Ctrl+C 为止。

服务端是以任务的形式在后台跑任务,植入的代码随着任务的中止而不会被执行,所以任务关闭后,不会对原有性能产生太大影响,而且原则上,任何Arthas命令不会引起原有业务逻辑的改变。

监控的维度说明

监控项说明
timestamp时间戳
classJava类
method方法(构造方法、普通方法)
total调用次数
success成功次数
fail失败次数
rt平均RT
fail-rate失败率

 

$ monitor -c 5 demo.MathGame primeFactors
Press Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 94 ms.timestamp            class          method        total  success  fail  avg-rt(ms)  fail-rate
-----------------------------------------------------------------------------------------------2018-12-03 19:06:38  demo.MathGame  primeFactors  5      1        4     1.15        80.00%timestamp            class          method        total  success  fail  avg-rt(ms)  fail-rate
-----------------------------------------------------------------------------------------------2018-12-03 19:06:43  demo.MathGame  primeFactors  5      3        2     42.29       40.00%timestamp            class          method        total  success  fail  avg-rt(ms)  fail-rate
-----------------------------------------------------------------------------------------------2018-12-03 19:06:48  demo.MathGame  primeFactors  5      3        2     67.92       40.00%timestamp            class          method        total  success  fail  avg-rt(ms)  fail-rate
-----------------------------------------------------------------------------------------------2018-12-03 19:06:53  demo.MathGame  primeFactors  5      2        3     0.25        60.00%timestamp            class          method        total  success  fail  avg-rt(ms)  fail-rate
-----------------------------------------------------------------------------------------------2018-12-03 19:06:58  demo.MathGame  primeFactors  1      1        0     0.45        0.00%timestamp            class          method        total  success  fail  avg-rt(ms)  fail-rate
-----------------------------------------------------------------------------------------------2018-12-03 19:07:03  demo.MathGame  primeFactors  2      2        0     3182.72     0.00%

watch

查看函数的参数、返回值、异常信息,如果有请求触发,就回打印对应的数据。用法如下

$ help watchUSAGE:watch [-b] [-e] [-x <value>] [-f] [-h] [-n <value>] [-E] [-M <value>] [-s] class-pattern method-pattern express [condition-express]SUMMARY:Display the input/output parameter, return object, and thrown exception of specified method invocationThe express may be one of the following expression (evaluated dynamically):target : the objectclazz : the object's classmethod : the constructor or methodparams : the parameters array of methodparams[0..n] : the element of parameters arrayreturnObj : the returned object of methodthrowExp : the throw exception of methodisReturn : the method ended by returnisThrow : the method ended by throwing exception#cost : the execution time in ms of method invocationExamples:watch -b org.apache.commons.lang.StringUtils isBlank paramswatch -f org.apache.commons.lang.StringUtils isBlank returnObjwatch org.apache.commons.lang.StringUtils isBlank '{params, target, returnObj}' -x 2watch -bf *StringUtils isBlank paramswatch *StringUtils isBlank params[0]watch *StringUtils isBlank params[0] params[0].length==1watch *StringUtils isBlank params '#cost>100'watch -E -b org\.apache\.commons\.lang\.StringUtils isBlank params[0]OPTIONS:-b, --before                                                        Watch before invocation-e, --exception                                                     Watch after throw exception-x, --expand <value>                                                Expand level of object (1 by default)-f, --finish                                                        Watch after invocation, enable by default-h, --help                                                          this help-n, --limits <value>                                                Threshold of execution times-E, --regex                                                         Enable regular expression to match (wildcard matching by default)-M, --sizeLimit <value>                                             Upper size limit in bytes for the result (10 * 1024 * 1024 by default)-s, --success                                                       Watch after successful invocation<class-pattern>                                                     The full qualified class name you want to watch<method-pattern>                                                    The method name you want to watch<express>                                                           the content you want to watch, written by ognl.Examples:paramsparams[0]'params[0]+params[1]''{params[0], target, returnObj}'returnObjthrowExptargetclazzmethod<condition-express>                                                 Conditional expression in ognl style, for example:TRUE  : 1==1TRUE  : trueFALSE : falseTRUE  : 'params.length>=0'FALSE : 1==2

具体执行如下(查看请求参数):

$ watch xxx.xxx.xxx.xxx.BerlinService view paramsPress Q or Ctrl+C to abort.
Affect(class-cnt:3 , method-cnt:3) cost in 393 ms.
ts=2019-05-17 14:43:36; [cost=37.391098ms] result=@Object[][@BerlinRequest[BerlinRequest(activityId=RC_12, userId=309314913, latitude=31.224360913038254, longitude=121.55064392834902, userAgent=Rajax/1 MI_MAX/helium Android/7.0 Display/NRD90M me/8.16.1 Channel/tengxun ID/e75ef7ec-4069-38ee-83c4-51fb7067f3e1; KERNEL_VERSION:3.10.84-perf-gd39c060 API_Level:24 Hardware: Mozilla/5.0 (Linux; Android 7.0; MI MAX Build/NRD90M; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/64.0.3282.137 Mobile Safari/537.36 AliApp(ELMC/8.16.1) TTID/offical WindVane/8.5.0,UT4Aplus/0.2.16, deviceId=null, limit=8, offset=0)],
]
ts=2019-05-17 14:43:36; [cost=46.358372ms] result=@Object[][@BerlinRequest[BerlinRequest(activityId=RC_12, userId=309314913, latitude=31.224360913038254, longitude=121.55064392834902, userAgent=Rajax/1 MI_MAX/helium Android/7.0 Display/NRD90M me/8.16.1 Channel/tengxun ID/e75ef7ec-4069-38ee-83c4-51fb7067f3e1; KERNEL_VERSION:3.10.84-perf-gd39c060 API_Level:24 Hardware: Mozilla/5.0 (Linux; Android 7.0; MI MAX Build/NRD90M; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/64.0.3282.137 Mobile Safari/537.36 AliApp(ELMC/8.16.1) TTID/offical WindVane/8.5.0,UT4Aplus/0.2.16, deviceId=null, limit=8, offset=0)],
]

查看请求参数及相应

$ watch xx.xxx.xx.xx.xxx.xx.BerlinService view '{params[0], returnObj}'Press Q or Ctrl+C to abort.
Affect(class-cnt:3 , method-cnt:3) cost in 416 ms.
ts=2019-05-17 14:52:38; [cost=33.968815ms] result=@ArrayList[@BerlinRequest[BerlinRequest(activityId=RC_12, userId=117043063, latitude=22.682775497436523, longitude=114.04010772705078, userAgent=Rajax/1 Apple/iPhone9,2 iOS/12.2 me/8.16.3 ID/6E92FDB8-FF9F-4F11-BC1A-490E67B39047; IsJailbroken/0 ASI/30F47DE7-0DE5-488E-A479-C94EB9284301 Mozilla/5.0 (iPhone; CPUiPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 AliApp(ELMC/8.16.3) UT4Aplus/0.0.4 WindVane/8.5.0 1242x2208 WK, deviceId=null, limit=8, offset=0)],@BerlinCommonResponse[xx.xxx.xx.xx.xxx.xx.BerlinCommonResponse@4c5df030],
]

可以看到,包含了请求及相应数据、整体cost-time,不过需要注意的是,这里并没有打印出所有详细数据。如果需要打印所有数据,加入-x参数表示遍历深度,可以调整来打印具体的参数和结果内容。默认-x 的深度为1,可以指定 2 3 等,如下:

$ watch xx.xxx.xx.xx.xxx.xx.BerlinService view '{params, returnObj}' -x 2
ts=2019-05-20 11:12:57; [cost=41.677987ms] result=@ArrayList[@Object[][@BerlinRequest[BerlinRequest(activityId=RC_12, userId=840800602, latitude=36.042474, longitude=103.849928, userAgent=Mozilla/5.0 (Linux; U; Android 8.1.0; zh-CN; DUB-AL00 Build/HUAWEIDUB-AL00) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/57.0.2987.108 UCBrowser/11.8.8.968 UWS/2.13.2.74 Mobile Safari/537.36 UCBS/2.13.2.74_190419112332 NebulaSDK/1.8.100112 Nebula AlipayDefined(nt:4G,ws:360|0|2.0) AliApp(AP/10.1.62.5549) AlipayClient/10.1.62.5549 Language/zh-Hans useStatusBar/true isConcaveScreen/true, deviceId=null, limit=8, offset=0)],],@BerlinCommonResponse[code=@String[200],message=@String[成功],data=@ArrayList[isEmpty=false;size=7],],
]

如过需要按照耗时进行过滤,需要加入: '#cost>200' 代表耗时超过200ms的才会打印出来。

watch/stack/trace这个三个命令都支持#cost

trace

方法内部调用路径,并输出方法路径上的每个节点上耗时

查看help

$ help traceUSAGE:trace [-h] [-j] [-n <value>] [-p <value>] [-E] class-pattern method-pattern [condition-express]SUMMARY:Trace the execution time of specified method invocation.FALSE : falseTRUE  : 'params.length>=0'FALSE : 1==2The express may be one of the following expression (evaluated dynamically):target : the objectclazz : the object's classmethod : the constructor or methodparams : the parameters array of methodparams[0..n] : the element of parameters arrayreturnObj : the returned object of methodthrowExp : the throw exception of methodisReturn : the method ended by returnisThrow : the method ended by throwing exception#cost : the execution time in ms of method invocationEXAMPLES:trace org.apache.commons.lang.StringUtils isBlanktrace *StringUtils isBlanktrace *StringUtils isBlank params[0].length==1trace *StringUtils isBlank '#cost>100'trace -E org\\.apache\\.commons\\.lang\\.StringUtils isBlanktrace -E com.test.ClassA|org.test.ClassB method1|method2|method3WIKI:https://alibaba.github.io/arthas/traceOPTIONS:-h, --help                                         this help-j, --jdkMethodSkip                                skip jdk method trace-n, --limits <value>                               Threshold of execution times-p, --path <value>                                 path tracing pattern-E, --regex                                        Enable regular expression to match (wildcard matching by default)<class-pattern>                                    Class name pattern, use either '.' or '/' as separator<method-pattern>                                   Method name pattern<condition-express>                                Conditional expression in ognl style, for example:TRUE  : 1==1TRUE  : true

平时主要使用-j (忽略jdk method trace)、'#cost>10'(过滤耗时时间) -n (执行次数)

$ trace xx.xxx.xx.xx.xxx.xx.QueryAction queryByReq  -j '#cost>5' -n 5Press Q or Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 781 ms.
`---ts=2019-05-20 15:27:10;thread_name=thread-272;id=1fb;is_daemon=false;priority=5;TCCL=sun.misc.Launcher$AppClassLoader@18b4aac2`---[12.250248ms] xx.xxx.xx.xx.xxx.xx.QueryAction:queryByReq()......

stack

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

很多时候我们都知道一个方法被执行,但这个方法被执行的路径非常多,或者你根本就不知道这个方法是从那里被执行了,此时你需要的是 stack 命令。

主要使用-n 命令,用于控制执行次数

stack xx.xxx.xx.xx.xxx.xx.QueryAction queryByReq -n 1

tt

先看个例子

$ tt -t xx.xxx.xx.xx.xxx.xx.QueryAction queryByReq -n 5
Press Q or Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 995 ms.IND  TIMESTAMP   COST(  IS-  IS  OBJECT    CLASS             METHODEX               ms)    RET  -EXP
--------------------------------------------------------------------------------100  2019-05-20  17.52  tru  fa  0x7df629  QueryValidSkuAct  queryValidSkuActi5     15:41:29   694    e    ls  87        ivityAction       vityByReqe100  2019-05-20  10.26  tru  fa  0x4bb52c  QueryValidSkuAct  queryValidSkuActi6     15:41:29   7017   e    ls  96        ivityAction       vityByReqe100  2019-05-20  19.80  tru  fa  0x20d351  QueryValidSkuAct  queryValidSkuActi7     15:41:29   7279   e    ls  d3        ivityAction       vityByReqe100  2019-05-20  19.84  tru  fa  0x286366  QueryValidSkuAct  queryValidSkuActi8     15:41:29   4526   e    ls  b4        ivityAction       vityByReqe100  2019-05-20  19.91  tru  fa  0x31297b  QueryValidSkuAct  queryValidSkuActi9     15:41:29   0582   e    ls  01        ivityAction       vityByReqe
Command execution times exceed limit: 5, so command will exit. You can set it with -n option.101  2019-05-20  19.94  tru  fa  0x7a3c2f  QueryValidSkuAct  queryValidSkuActi0     15:41:29   8529   e    ls  c4        ivityAction       vityByReq
  • 表格字段说明
表格字段字段解释
INDEX时间片段记录编号,每一个编号代表着一次调用,后续tt还有很多命令都是基于此编号指定记录操作,非常重要。
TIMESTAMP方法执行的本机时间,记录了这个时间片段所发生的本机时间
COST(ms)方法执行的耗时
IS-RET方法是否以正常返回的形式结束
IS-EXP方法是否以抛异常的形式结束
OBJECT执行对象的hashCode(),注意,曾经有人误认为是对象在JVM中的内存地址,但很遗憾他不是。但他能帮助你简单的标记当前执行方法的类实体
CLASS执行的类名
METHOD执行的方法名

-t

tt 命令有很多个主参数,-t 就是其中之一。这个参数的表明希望记录下类 *Testprint 方法的每次执行情况。

-n 3

当你执行一个调用量不高的方法时可能你还能有足够的时间用 CTRL+C 中断 tt 命令记录的过程,但如果遇到调用量非常大的方法,瞬间就能将你的 JVM 内存撑爆。

此时你可以通过 -n 参数指定你需要记录的次数,当达到记录次数时 Arthas 会主动中断tt命令的记录过程,避免人工操作无法停止的情况。

检索调用记录

当你用 tt 记录了一大片的时间片段之后,你希望能从中筛选出自己需要的时间片段,这个时候你就需要对现有记录进行检索。

假设我们有这些记录

$ tt -lINDEX   TIMESTAMP            COST(ms)  IS-RET  IS-EXP   OBJECT         CLASS                          METHOD
-------------------------------------------------------------------------------------------------------------------------------------1000    2018-12-04 11:15:38  1.096236  false   true     0x4b67cf4d     MathGame                       primeFactors1001    2018-12-04 11:15:39  0.191848  false   true     0x4b67cf4d     MathGame                       primeFactors1002    2018-12-04 11:15:40  0.069523  false   true     0x4b67cf4d     MathGame                       primeFactors1003    2018-12-04 11:15:41  0.186073  false   true     0x4b67cf4d     MathGame                       primeFactors1004    2018-12-04 11:15:42  17.76437  true    false    0x4b67cf4d     MathGame                       primeFactors91005    2018-12-04 11:15:43  0.4776    false   true     0x4b67cf4d     MathGame                       primeFactors
Affect(row-cnt:6) cost in 4 ms.

我需要筛选出 primeFactors 方法的调用信息

$ tt -s 'method.name=="primeFactors"'INDEX   TIMESTAMP            COST(ms)  IS-RET  IS-EXP   OBJECT         CLASS                          METHOD
-------------------------------------------------------------------------------------------------------------------------------------1000    2018-12-04 11:15:38  1.096236  false   true     0x4b67cf4d     MathGame                       primeFactors1001    2018-12-04 11:15:39  0.191848  false   true     0x4b67cf4d     MathGame                       primeFactors1002    2018-12-04 11:15:40  0.069523  false   true     0x4b67cf4d     MathGame                       primeFactors1003    2018-12-04 11:15:41  0.186073  false   true     0x4b67cf4d     MathGame                       primeFactors1004    2018-12-04 11:15:42  17.76437  true    false    0x4b67cf4d     MathGame                       primeFactors91005    2018-12-04 11:15:43  0.4776    false   true     0x4b67cf4d     MathGame                       primeFactors
Affect(row-cnt:6) cost in 607 ms.

你需要一个 -s 参数。同样的,搜索表达式的核心对象依旧是 Advice 对象。

查看调用信息

对于具体一个时间片的信息而言,你可以通过 -i 参数后边跟着对应的 INDEX 编号查看到他的详细信息。

$ tt -i 1003INDEX            1003GMT-CREATE       2018-12-04 11:15:41COST(ms)         0.186073OBJECT           0x4b67cf4dCLASS            demo.MathGameMETHOD           primeFactorsIS-RETURN        falseIS-EXCEPTION     truePARAMETERS[0]    @Integer[-564322413]THROW-EXCEPTION  java.lang.IllegalArgumentException: number is: -564322413, need >= 2at demo.MathGame.primeFactors(MathGame.java:46)at demo.MathGame.run(MathGame.java:24)at demo.MathGame.main(MathGame.java:16)Affect(row-cnt:1) cost in 11 ms.

重做一次调用

当你稍稍做了一些调整之后,你可能需要前端系统重新触发一次你的调用,此时得求爷爷告奶奶的需要前端配合联调的同学再次发起一次调用。而有些场景下,这个调用不是这么好触发的。

tt 命令由于保存了当时调用的所有现场信息,所以我们可以自己主动对一个 INDEX 编号的时间片自主发起一次调用,从而解放你的沟通成本。此时你需要 -p 参数。通过 --replay-times 指定 调用次数,通过 --replay-interval 指定多次调用间隔(单位ms, 默认1000ms)

$ tt -i 1004 -pRE-INDEX       1004GMT-REPLAY     2018-12-04 11:26:00OBJECT         0x4b67cf4dCLASS          demo.MathGameMETHOD         primeFactorsPARAMETERS[0]  @Integer[946738738]IS-RETURN      trueIS-EXCEPTION   falseCOST(ms)         0.186073RETURN-OBJ     @ArrayList[@Integer[2],@Integer[11],@Integer[17],@Integer[2531387],]
Time fragment[1004] successfully replayed.
Affect(row-cnt:1) cost in 14 ms.

你会发现结果虽然一样,但调用的路径发生了变化,有原来的程序发起变成了 Arthas 自己的内部线程发起的调用了。

  • 需要强调的点

    1. ThreadLocal 信息丢失

      很多框架偷偷的将一些环境变量信息塞到了发起调用线程的 ThreadLocal 中,由于调用线程发生了变化,这些 ThreadLocal 线程信息无法通过 Arthas 保存,所以这些信息将会丢失。

      一些常见的 CASE 比如:鹰眼的 TraceId 等。

    2. 引用的对象

      需要强调的是,tt 命令是将当前环境的对象引用保存起来,但仅仅也只能保存一个引用而已。如果方法内部对入参进行了变更,或者返回的对象经过了后续的处理,那么在 tt 查看的时候将无法看到当时最准确的值。这也是为什么 watch 命令存在的意义。


 

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

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

相关文章

jzoj6307-安排【归并排序】

正题 题目大意 一个目前序列&#xff0c;一个目标序列&#xff0c;每次可以选择一个区间交换区间最大值和最小值。 询问在345678345678345678步内将目前序列转换回目标序列的方案(输出该方案)。 解题思路 我们考虑归并排序&#xff0c;对于两个升序的序列&#xff0c;我们考…

.NET Core 2.1 Preview 1发布:更快的构建性能

今天&#xff0c;我们宣布发布 .NET Core 2.1 Preview 1。这是 .NET Core 2.1 的第一个公开发布。我们有很大的改进希望分享出来&#xff0c;并且渴望得到您的反馈意见&#xff0c;无论是在评论中还是在github中dotnet/core #1297ASP.NET Core 2.1 Preview 1 和 Entity Framewo…

Spark SQL(七)之基于用户的相似度公式

一、基于用户的Jaccard相似度公式 其中&#xff0c;u、v表示任意两个用户&#xff0c;N(u)表示用户u喜欢的物品集合,N(v)表示用户v喜欢物品的集合。 代码 public class UserCFApp {public static void main(String[]args){SparkConf sparkConf new SparkConf();sparkConf.se…

欢乐纪中A组赛【2019.8.17】

前言 前几天题目没改完(好难QvQQvQQvQ)&#xff0c;然后这几天ZZYZZYZZY和WHFWHFWHF去广州二中了 然后我是菜鸡&#xff0c;今天暴力写挂了QAQQAQQAQ&#xff0c;T2T2T2少判断了个东西少了808080 成绩 懒得写只放自己的了(反正垫底) Rank51,20ptsRank51,20ptsRank51,20pts 正…

BXUG第11期活动

分享主题&#xff1a;Xamarin Azure 微软云加端移动应用技术架构分享者&#xff1a;周岳 微软MVP分享主题&#xff1a;从设计图到最终界面- Xamarin跨平台界面最佳实践分享者: 程文锋 视高盛景分享主题&#xff1a;基于VSTS的App DevOps分享者&#xff1a; 安庭庭 张浩 视高…

Spark SQL(八)之基于物品的相似度公式

一、基于物品的Jaccard相似度公式 其中&#xff0c;i、j表示任意两个物品&#xff0c;N(i)表示喜欢物品i的用户数&#xff0c;N(j)表示喜欢物品j的用户数。 代码&#xff1a; public class ItemCFApp {public static void main(String[]args){SparkConf sparkConf new Spark…

ASP.NET CORE MVC 实现减号分隔(Kebab case)样式的 URL

ASP.NET CORE MVC 中&#xff0c;默认的 Route 模板是&#xff1a; /{controller}/{action} 。我们可以通过开启 URL 小写转换将 URL 变为小写&#xff0c;但此方式在 Controller 或者 Action 为一个词组时&#xff0c;生成的 URL 并不友好。假设我们有 UserController 和 Add…

Spark SQL(九)之基于用户的推荐公式

一、基于用户的推荐公式 其中&#xff0c;S(u,K)表示与用户u最相似的K个用户&#xff0c;N(i)代表喜欢物品i的用户集合&#xff0c;rm表示用户v对物品i的评分。 二、代码 public class UserCFRecommendApp {public static void main(String[]args){SparkConf sparkConf new S…

jzoj6309-完全背包【贪心,背包】

正题 题目大意 完全背包&#xff0c;不过容量特别大。 解题思路 然后我们可以先做一个1∼200001\sim 200001∼20000的背包&#xff0c;然后枚举一个大小&#xff0c;然后将这个大小填入背包知道无法填入为止&#xff0c;然后剩下的空位在再一次背包就好。 codecodecode #incl…

拥抱.NET Core系列:MemoryCache 缓存过期

MSCache项目MSCache目前最新的正式版是 2.0.0&#xff0c;预览版是2.1.0&#xff0c;会与.NETCore 2.1一起发布。本篇用了2.0.0版本开源在GitHub上&#xff0c;仓库地址是&#xff1a;https://github.com/aspnet/CachingNuGet地址为&#xff1a;https://www.nuget.org/packages…

Spark SQL(十)之基于物品的推荐公式

一、基于物品的推荐公式 其中&#xff0c;S(j,K)表示与物品j最相似的K个物品&#xff0c;N(u)表示用户u喜欢的物品集合&#xff0c;Rui表示用户u对物品i的评分。 二、代码 public class ItemCFRecommendApp {public static void main(String[]args){SparkConf sparkConf new …

jzoj6308-中间值【分治】

正题 题目大意 两个序列不降a,ba,ba,b&#xff0c;每次可以修改或询问[l1,r1,l2,r2][l_1,r_1,l_2,r_2][l1​,r1​,l2​,r2​]要求输出将序列aaa的l1∼r1l_1\sim r_1l1​∼r1​和bbb的l2∼r2l_2\sim r_2l2​∼r2​部分合起来然后求中位数。 解题思路 我们考虑分治&#xff0c;…

ASP.NET Core Razor 页面使用教程

ASP.NET Core Razor 页面作为 ASP.NET Core 2.0的一部分发布&#xff0c;它是基于页面的全新的Web开发框架。如果您想学习如何使用 ASP.NET Core Razor 页面&#xff0c;可以访问微软的官方站点https://docs.microsoft.com/zh-cn/aspnet/core/tutorials/razor-pages/razor-page…

如何面试.NET/ASP.NET工程师?

2018-2-28 更新&#xff1a;距离这篇回答发布已经五年过去了&#xff0c;最近还经常受到关注。技术本身在发展&#xff0c;这令我感到有必要来更新一下&#xff0c;希望对新看到的朋友有用。对于服务器上的 .NET 技术&#xff0c;最新的发展当然是 .NET Core 了&#xff0c;作为…

欢乐纪中A组赛【2019.8.18】

前言 有一个暴力写挂了QVQQVQQVQ 成绩 RankRankRankPersonPersonPersonScoreScoreScoreAAABBBCCC111111(J−3)LRZ(J-3)LRZ(J−3)LRZ140140140100100100303030101010191919(J−3)WYC(J-3)WYC(J−3)WYC120120120100100100101010101010262626(J−3)HZB(J-3)HZB(J−3)HZB100100100…

Asp.Net Core 2.1+的视图缓存(响应缓存)

响应缓存Razor 页与 ASP.NET 核心 2.0 中不支持。 此功能将支持ASP.NET 核心 2.1 版本。在老的版本的MVC里面&#xff0c;有一种可以缓存视图的特性(OutputCache)&#xff0c;可以保持同一个参数的请求&#xff0c;在N段时间内&#xff0c;直接从mvc的缓存中读取&#xff0c;不…

Json.NET 不再有超过120个依赖项

Json.NET是.NET的官方的JSON解析和序列化库&#xff0c;它取代了Microsoft实际提供的库。但是当把Json.NET推向.NET Standard时&#xff0c;出现了一些问题。除了在该平台上无法使用的众多方法之外&#xff0c;在NET Standard 1.3上的Json.NET需要高达122个依赖包。随着适用于.…

C#热度不如Java?网友呛声:还有使用C#不能完成的工作?

C#是微软公司发布的一种面向对象的、运行于.NET Framework之上的高级程序设计语言&#xff0c;自发布以来受到了程序员的广泛关注。C#与Java有着很多相似之处&#xff0c;例如&#xff0c;单一继承、接口、与Java几乎同样的语法和编译成中间代码再运行的过程。但是与Java每月被…

EntityFramework Core 2.0执行原始查询如何防止SQL注入?

前言接下来一段时间我们来讲讲EntityFramework Core基础&#xff0c;精简的内容&#xff0c;深入浅出&#xff0c;希望为想学习EntityFramework Core的童鞋提供一点帮助。EntityFramework Core执行原始查询在EntityFramework Core中执行原始查询我们借助FromSql来实现&#xff…

EntityFramework Core 2.0自定义标量函数两种方式

前言上一节我们讲完原始查询如何防止SQL注入问题同时并提供了几种方式。本节我们继续来讲讲EF Core 2.0中的新特性自定义标量函数。自定义标量函数两种方式在EF Core 2.0中我们可以将方法映射到数据库中的标量函数&#xff0c;我们可在LINQ中调用此方法并会被正确翻译成SQL语句…