8

深度剖析 Java 应用诊断利器---Arthas

 2 years ago
source link: https://www.51cto.com/article/708741.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client
66e34da673a064e76d4908f9d020d4d92a0c2b.png

在介绍 Arthas 之前,大家肯定经历过生产环境遇到Java服务出现问题,最常见的情况就是调用第三方接口出现异常,正好没有打日志,异常堆栈也无法证明是 「谁的锅」。此时你只能焦头烂额一顿操作也无事无补。早些接触到 Arthas 也就可以轻松解决这类问题,同时还可以帮忙我们排查和解决很多常见远程服务的问题。

Arthas(阿尔萨斯)

Arthas 是 Alibaba 开源的 Java 诊断工具,支持 JDK 6+,支持 Linux/Mac/Windows,采用命令行交互模式,同时提供丰富的 Tab 自动补全功能,进一步方便进行问题的定位和诊断。

开源地址:https://github.com/alibaba/arthas。

官方文档:https://github.com/alibaba/arthas。

Arthas 可以帮助我们解决哪些问题:

  1. 这个类从哪个 jar 包加载的?为什么会报各种类相关的 Exception?
  2. 我改的代码为什么没有执行到?难道是我没 commit?分支搞错了?
  3. 遇到问题无法在线上 debug,难道只能通过加日志再重新发布吗?
  4. 线上遇到某个用户的数据处理有问题,但线上同样无法 debug,线下无法重现!
  5. 是否有一个全局视角来查看系统的运行状况?
  6. 有什么办法可以监控到 JVM 的实时运行状态?
  7. 怎么快速定位应用的热点,生成火焰图?

使用 arthas(阿尔萨斯)

采用命令行交互模式,同时提供丰富的 Tab 自动补全功能

1、 安装 arthas

curl -O https://arthas.aliyun.com/arthas-boot.jar
java -jar arthas-boot.jar

「注意可能遇到的的问题:」

  • 执行该程序的用户需要和目标进程具有相同的权限。比如以admin用户来执行:sudo su admin && java -jar arthas-boot.jar 或 sudo -u admin -EH java -jar arthas-boot.jar。
  • 如果attach不上目标进程,可以查看~/logs/arthas/ 目录下的日志。
  • java -jar arthas-boot.jar -h 打印更多参数信息。

2、 选择应用java进程

java -jar arthas-boot.jar
# 选择服务序列,可以通过 java -jar arthas-boot.jar -h 打印更多参数信息
a6d158370097ce881766346d3964c870396af1.png

这边遇到报错提示**Can not find tools.**,指定本地jdk全路径执行即可:Such as /opt/jdk/bin/java -jar arthas-boot.jar。

/Library/Java/JavaVirtualMachines/jdk1.8.0_281.jdk/Contents/Home/bin/java -jar arthas-boot.jar
b37cb0763fd9362d25d802264a4cf9c0bf3ae1.png

「看到这个界面就可以开始你的操作了」

3、 Arthas web console

「Arthas」 目前支持 Web Console,在成功启动连接进程之后就已经自动启动,可以直接访问 http://127.0.0.1:8563/ 访问,页面上的操作模式和控制台完全一样。

d2e3aa518357ccb76cc3803263dc44fc71ec9f.png

4、常用命令

下面列举一些 「Arthas」 的常用命令,后面会介绍一些常用的命令。后续的命令介绍内容有些生硬,可以先收藏起来大致了解每个命令的作用,未来遇到至少还是有手段可以排查。

c302fbd632acecae8ef47479f423dfd9d08964.jpg

(1) dashboard 命令

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

81e78c733aef99f858e81804cddc0a24db3925.png

(2) thread 命令

查看当前线程信息,查看线程的堆栈。

  • -i: 指定时间内采集。
thread -i 2000
887ecb6006fc1e216c757361c01b55fb714a94.png
  • -n: 找出 cpu 使用率最高的几个线程。
thread -n 3
[arthas@1]$ thread -n 3
"C1 CompilerThread1" [Internal] cpuUsage=2.59% deltaTime=5ms time=18214ms
"arthas-command-execute" Id=2261 cpuUsage=0.81% deltaTime=1ms time=119ms RUNNABLE
    at 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:206)
    at com.taobao.arthas.core.command.monitor200.ThreadCommand.process(ThreadCommand.java:122)
    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:385)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180)
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
    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)
"C2 CompilerThread0" [Internal] cpuUsage=0.31% deltaTime=0ms time=94495ms
  • -b: 找到持有锁的线程,有时候请求后,一直卡住,那么可以使用该方式去查找持有锁的线程。注意该方式不支持显示锁也就是lock接口的。
thread -b
[arthas@1]$ thread -b
No most blocking thread found!

(3) watch 命令

这个命令也是最常用、最好用的命令之一,方法执行数据观测。可以观察远程服务器方法的调用出入参、异常情况。

常用参数:

  • -x: 指定输出结果的属性遍历深度,默认为 1。
  • -b: 在「方法调用之前」观察。
  • -e: 在「方法异常之后」观察。
  • -s: 在「方法返回之后」观察。
  • -f: 在「方法结束之后」(正常返回和异常返回)观察。

观察方法出参和返回值。

[arthas@1]$ watch com.xx.actionlog.impl.ActionLogConfigApiImpl listTopics  "{params,returnObj}" -x 2
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 1) cost in 238 ms, listenerId: 6
method=com.xx.actionlog.impl.ActionLogConfigApiImpl.listTopics location=AtExit
ts=2021-05-21 14:43:01; [cost=135.092231ms] result=@ArrayList[
    @Object[][
        @String[K8SOFFICE],
        @String[default],
    ],
    @ArrayList[
        @String[orders],
        @String[orderlogs],
        @String[operationlogs],
        @String[store],
        @String[stores],
        @String[place],
        @String[tag],
        @String[channel],
        @String[suppliers],
        @String[auth],
        @String[site],
    ],
]

观察方法入参。

[arthas@1]$ watch com.xx.actionlog.impl.ActionLogConfigApiImpl listTopics  "{params,returnObj}" -x 2 -b
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 1) cost in 209 ms, listenerId: 7
method=com.xx.actionlog.impl.ActionLogConfigApiImpl.listTopics location=AtEnter
ts=2021-05-21 14:55:34; [cost=0.054197ms] result=@ArrayList[
    @Object[][
        @String[K8SOFFICE],
        @String[default],
    ],
    null,
]

同时观察方法调用前和方法返回后。

[arthas@1]$ watch com.xx.actionlog.impl.ActionLogConfigApiImpl listTopics  "{params,target,returnObj}" -x 2 -b -s -n 2
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 1) cost in 190 ms, listenerId: 8
method=com.xx.actionlog.impl.ActionLogConfigApiImpl.listTopics location=AtEnter
ts=2021-05-21 14:57:18; [cost=0.035688ms] result=@ArrayList[
    @Object[][
        @String[K8SOFFICE],
        @String[default],
    ],
    @ActionLogConfigApiImpl[
        log=@Logger[Logger[com.xx.actionlog.impl.ActionLogConfigApiImpl]],
        DEFAULT_CLUSTER=@String[default],
        DEFAULT_NAMESPACE=@String[application],
        DEFAULT_ACTION_LOG_NAMESPACE=@String[actionLogConfig],
        apolloOperationService=@ApolloOperationService[com.xx.actionlog.service.ApolloOperationService@9470ab3],
        $jacocoData=@boolean[][isEmpty=false;size=91],
    ],
    null,
]
method=com.xx.actionlog.impl.ActionLogConfigApiImpl.listTopics location=AtExit
ts=2021-05-21 14:57:18; [cost=1.4527299465320627E10ms] result=@ArrayList[
    @Object[][
        @String[K8SOFFICE],
        @String[default],
    ],
    @ActionLogConfigApiImpl[
        log=@Logger[Logger[com.xx.actionlog.impl.ActionLogConfigApiImpl]],
        DEFAULT_CLUSTER=@String[default],
        DEFAULT_NAMESPACE=@String[application],
        DEFAULT_ACTION_LOG_NAMESPACE=@String[actionLogConfig],
        apolloOperationService=@ApolloOperationService[com.xx.actionlog.service.ApolloOperationService@9470ab3],
        $jacocoData=@boolean[][isEmpty=false;size=91],
    ], 
    @ArrayList[
        @String[orders],
        @String[orderlogs],
        @String[operationlogs],
        @String[store],
        @String[stores],
        @String[place],
        @String[tag],
        @String[channel],
        @String[suppliers],
        @String[auth],
        @String[site],
    ],
]
Command execution times exceed limit: 2, so command will exit. You can set it with -n option.

(4) sc 命令

Search-Class英文的缩写,用于查看JVM已加载的类信息。

常用参数:

  • -d: 参数用于输出详细的类相关信息(类全限定名,存放路径,接口,注解,继承父类,类加载器等),支持模糊查询。
  • -f: 参数需要配合 -d 命令一起使用, 在上述类信息中加入字段信息,包括权限、类型、名字。
sc -d -f *TableInfoServiceImpl
[arthas@1]$ sc -d -f *TableInfoServiceImpl
 class-info        com.xx.consumer.actionlog.service.impl.TableInfoServiceImpl                                                                               
 code-source       file:/app/action-log-consumer.jar!/BOOT-INF/classes!/                                                                                       
 name              com.xx.consumer.actionlog.service.impl.TableInfoServiceImpl                                                                               
 isInterface       false                                                                                                                                       
 isAnnotation      false                                                                                                                                       
 isEnum            false                                                                                                                                       
 isAnonymousClass  false                                                                                                                                       
 isArray           false                                                                                                                                       
 isLocalClass      false                                                                                                                                       
 isMemberClass     false                                                                                                                                       
 isPrimitive       false                                                                                                                                       
 isSynthetic       false                                                                                                                                       
 simple-name       TableInfoServiceImpl                                                                                                                        
 modifier          public                                                                                                                                      
 annotation        org.springframework.stereotype.Service                                                                                                      
 interfaces        com.xx.consumer.actionlog.service.TableInfoService                                                                                        
 super-class       +-java.lang.Object                                                                                                                          
 class-loader      +-org.springframework.boot.loader.LaunchedURLClassLoader@7fad8c79                                                                           
                     +-sun.misc.Launcher$AppClassLoader@18b4aac2                                                                                               
                       +-sun.misc.Launcher$ExtClassLoader@63c4310c                                                                                             
 classLoaderHash   7fad8c79                                                                                                                                    
 fields            name     log                                                                                                                                
                   type     org.slf4j.Logger                                                                                                                   
                   modifier final,private,static                                                                                                               
                   value    Logger[com.xx.consumer.actionlog.service.impl.TableInfoServiceIm                                                                 
                            pl]                                                                                                                                
                                                                                                                                                               
                   name       actionLogConfigProperties                                                                                                        
                   type       com.xx.consumer.actionlog.properties.ActionLogConfigProperties                                                                 
                   modifier   private                                                                                                                          
                   annotation org.springframework.beans.factory.annotation.Autowired                                                                           
                                                                                                                                                               
                   name     $jacocoData                                                                                                                        
                   type     []                                                                                                                                 
                   modifier private,static,transient                                                                                                           
                   value    [Z@4494fa9e                                                                                                                        
                                                                                                                                                               

Affect(row-cnt:1) cost in 47 ms.

其他参数:

  • -E: 开启正则表达式匹配,默认为通配符匹配。
  • -c: 类名表达式匹配。

(5) sm 命令

Search-Method英文的缩写,用于查看已加载类的方法信息。

常用参数:

  • -d: 方法详情。
sm -d *ActionLogServiceImpl process
[arthas@1]$ sm -d *ActionLogServiceImpl process
 declaring-class  com.xx.consumer.actionlog.service.impl.ActionLogServiceImpl                                                                                
 method-name      process                                                                                                                                      
 modifier         public                                                                                                                                       
 annotation                                                                                                                                                    
 parameters       java.lang.String                                                                                                                             
 return           void                                                                                                                                         
 exceptions                                                                                                                                                    
 classLoaderHash  7fad8c79                                                                                                                                     
Affect(row-cnt:1) cost in 48 ms.

其他参数:

  • -E: 开启正则表达式匹配,默认为通配符匹配。
  • -c: 类名表达式匹配。

(6) jad 命令

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

jad *TableInfoServiceImpl
[arthas@1]$ jad *TableInfoServiceImpl
ClassLoader:                                                                                                                                                   
+-org.springframework.boot.loader.LaunchedURLClassLoader@7fad8c79                                                                                              
  +-sun.misc.Launcher$AppClassLoader@18b4aac2                                                                                                                  
    +-sun.misc.Launcher$ExtClassLoader@63c4310c                                                                                                                
Location:                                                                                                                                                      
file:/app/action-log-consumer.jar!/BOOT-INF/classes!/                                                                                                          
       /*
        * Decompiled with CFR.
        * 
        * Could not load the following classes:
        *  com.xx.consumer.actionlog.properties.ActionLogConfigProperties
        *  com.xx.consumer.actionlog.properties.ActionLogConfigProperties$ActionLogConfigItem
        *  com.xx.consumer.actionlog.properties.AttentionFieldConfig
        *  com.xx.consumer.actionlog.service.TableInfoService
        *  org.slf4j.Logger
        *  org.slf4j.LoggerFactory
        *  org.springframework.beans.factory.annotation.Autowired
        *  org.springframework.stereotype.Service
        */
       package com.xx.consumer.actionlog.service.impl;
       
       import com.xx.consumer.actionlog.properties.ActionLogConfigProperties;
       import com.xx.consumer.actionlog.properties.AttentionFieldConfig;
       import com.xx.consumer.actionlog.service.TableInfoService;
       import org.slf4j.Logger;
       import org.slf4j.LoggerFactory;
       import org.springframework.beans.factory.annotation.Autowired;
       import org.springframework.stereotype.Service;       
       @Service
       public class TableInfoServiceImpl
       implements TableInfoService {
           private static final Logger log;
           @Autowired
           private ActionLogConfigProperties actionLogConfigProperties;
           private static transient /* synthetic */ boolean[] $jacocoData;      
           public TableInfoServiceImpl() {
               boolean[] blArray = TableInfoServiceImpl.$jacocoInit();
               blArray[0] = true;
           }       
           /*
            * WARNING - void declaration
            */
           public String getColumnCommentByTableNameAndColumnName(String string, String string2) {
               String desc;
               void columnName;
               boolean[] blArray = TableInfoServiceImpl.$jacocoInit();
/*18*/         void var4_4 = columnName;
               try {
                   void tableName;
                   blArray[1] = true;
/*20*/             desc = ((AttentionFieldConfig)((ActionLogConfigProperties.ActionLogConfigItem)this.actionLogConfigProperties.getConfig().get(tableName)).getAttentionFields().get(columnName)).getDesc();
/*23*/             blArray[2] = true;
               }
               catch (Exception exception) {
                   void e;
                   blArray[3] = true;
/*22*/             log.warn(e.getMessage(), (Throwable)e);
                   blArray[4] = true;
               }
               blArray[5] = true;
               return desc;
           }       
           static {
               boolean[] blArray = TableInfoServiceImpl.$jacocoInit();
/*10*/         log = LoggerFactory.getLogger(TableInfoServiceImpl.class);
               blArray[6] = true;
           }       
           private static /* synthetic */ boolean[] $jacocoInit() {
               boolean[] blArray = $jacocoData;
               if ($jacocoData == null) {
                   Object[] objectArray = new Object[]{883735039782912886L, "com/xx/consumer/actionlog/service/impl/TableInfoServiceImpl", 7};
                   UnknownError.$jacocoAccess.equals(objectArray);
                   blArray = $jacocoData = (boolean[])objectArray[0];
               }
               return blArray;
           }
       }
Affect(row-cnt:1) cost in 253 ms.

(7) jvm 命令

输出 jvm 相关信息,包括加载类的路径,启动类路径,加载类个数等等。

(8) trace 命令

方法内部调用路径,并输出方法路径上的每个节点上耗时,「用于接口性能定位和调优的时候使用」。

常用参数:

  • -n: 有时候请求量太大,我们不需要每个请求调用时间,那么可以使用这个参数,指定次数调用后结束。
trace *ActionLogConfigApiImpl listTopics -n 2
[arthas@1]$ trace *ActionLogConfigApiImpl listTopics -n 2
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 1) cost in 237 ms, listenerId: 3
`---ts=2021-05-21 14:22:43;thread_name=http-nio-8047-exec-5;id=59;is_daemon=true;priority=5;TCCL=org.springframework.boot.loader.LaunchedURLClassLoader@7fad8c79
    `---[158.020381ms] com.xx.actionlog.impl.ActionLogConfigApiImpl:listTopics()
        +---[0.063066ms] com.xx.actionlog.impl.ActionLogConfigApiImpl:$jacocoInit() #25
        +---[0.035828ms] com.xx.utils.StringUtils:isEmpty() #108
        +---[0.02172ms] com.xx.utils.StringUtils:isEmpty() #114
        `---[157.534007ms] com.xx.actionlog.service.ApolloOperationService:listKafkaTopics() #117

`---ts=2021-05-21 14:22:51;thread_name=http-nio-8047-exec-9;id=5d;is_daemon=true;priority=5;TCCL=org.springframework.boot.loader.LaunchedURLClassLoader@7fad8c79
    `---[173.617716ms] com.xx.actionlog.impl.ActionLogConfigApiImpl:listTopics()
        +---[0.025143ms] com.xx.actionlog.impl.ActionLogConfigApiImpl:$jacocoInit() #25
        +---[0.023677ms] com.xx.utils.StringUtils:isEmpty() #108
        +---[0.017739ms] com.xx.utils.StringUtils:isEmpty() #114
        `---[173.398065ms] com.xx.actionlog.service.ApolloOperationService:listKafkaTopics() #117

Command execution times exceed limit: 2, so command will exit. You can set it with -n option.

(9) stack 命令

输出当前方法被调用的调用路径,「当前方法可能会调用不同路径的时候,可以使用该命令跟踪调用链路」。

常用参数:

  • -n: 指定结束次数,达到次数则自动退出,不继续监听。
stack *ActionLogConfigApiImpl listTopics -n 1

查看 ActionLogConfigApiImpl 类 listTopics 方法调用链路。

[arthas@1]$ stack *ActionLogConfigApiImpl listTopics -n 1
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 1) cost in 545 ms, listenerId: 1
ts=2021-05-21 13:51:59;thread_name=http-nio-8047-exec-2;id=56;is_daemon=true;priority=5;TCCL=org.springframework.boot.loader.LaunchedURLClassLoader@7fad8c79
    @com.xx.actionlog.impl.ActionLogConfigApiImpl.listTopics()
        at org.apache.dubbo.common.bytecode.Wrapper3.invokeMethod(Wrapper3.java:-1)
        at org.apache.dubbo.rpc.proxy.javassist.JavassistProxyFactory$1.doInvoke(JavassistProxyFactory.java:47)
        at org.apache.dubbo.rpc.proxy.AbstractProxyInvoker.invoke(AbstractProxyInvoker.java:84)
        at com.xx.apache.dubbo.filter.xxExceptionFilter.invoke(xxExceptionFilter.java:53)
        at org.apache.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:81)
        at org.apache.dubbo.monitor.support.MonitorFilter.invoke(MonitorFilter.java:89)
        at org.apache.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:81)
        at com.alibaba.dubbo.rpc.Invoker$CompatibleInvoker.invoke(Invoker.java:55)
        at com.xx.zipkin.dubbo.ZipkinDubboFilter.invoke(ZipkinDubboFilter.java:84)
        at com.alibaba.dubbo.rpc.Filter.invoke(Filter.java:29)
        at org.apache.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:81)
        at org.apache.dubbo.rpc.filter.TimeoutFilter.invoke(TimeoutFilter.java:44)
        at org.apache.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:81)
        at org.apache.dubbo.rpc.protocol.dubbo.filter.TraceFilter.invoke(TraceFilter.java:77)
        at org.apache.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:81)
        at org.apache.dubbo.rpc.filter.ExecuteLimitFilter.invoke(ExecuteLimitFilter.java:56)
        at org.apache.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:81)
        at org.apache.dubbo.rpc.filter.ContextFilter.invoke(ContextFilter.java:118)
        at org.apache.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:81)
        at org.apache.dubbo.rpc.filter.GenericFilter.invoke(GenericFilter.java:152)
        at org.apache.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:81)
        at org.apache.dubbo.rpc.filter.ClassLoaderFilter.invoke(ClassLoaderFilter.java:38)
        at org.apache.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:81)
        at org.apache.dubbo.rpc.filter.EchoFilter.invoke(EchoFilter.java:41)
        at org.apache.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:81)
        at org.apache.dubbo.rpc.protocol.injvm.InjvmInvoker.doInvoke(InjvmInvoker.java:63)
        at org.apache.dubbo.rpc.protocol.AbstractInvoker.invoke(AbstractInvoker.java:162)
        at org.apache.dubbo.rpc.protocol.AsyncToSyncInvoker.invoke(AsyncToSyncInvoker.java:52)
        at org.apache.dubbo.monitor.support.MonitorFilter.invoke(MonitorFilter.java:89)
        at org.apache.dubbo.rpc.protocol.ProtocolFilterWrapper$1.in
        voke(ProtocolFilterWrapper.java:81)
        at com.alibaba.dubbo.rpc.Invoker$CompatibleInvoker.invoke(Invoker.java:55)
        at com.xx.zipkin.dubbo.ZipkinDubboFilter.invoke(ZipkinDubboFilter.java:84)        
        ....        
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
        at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:109)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
        at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:93)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
        at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
        at org.springframework.boot.actuate.autoconfigure.MetricsFilter.doFilterInternal(MetricsFilter.java:100)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
        at com.xx.web.filters.SimpleCORSFilter.doFilter(SimpleCORSFilter.java:38)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
        at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:493)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:137)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
        at org.apache.catalina.valves.RemoteIpValve.invoke(RemoteIpValve.java:679)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
        at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:798)
        at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
        at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:808)
        at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1498)
        at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
        at java.lang.Thread.run(Thread.java:748)
Command execution times exceed limit: 1, so command will exit. You can set it with -n option.

(10) stack 命令

执行ognl表达式。

调用静态函数。

$ ognl '@[email protected]("hello")'
null

查看静态变量值(注意hashcode是变化的,需要先查看当前的ClassLoader信息,提取对应ClassLoader的hashcode)。

通过hashcode指定ClassLoader:

[arthas@1]$ classloader -t
+-BootstrapClassLoader                                                                                                                                         
+-sun.misc.Launcher$ExtClassLoader@7611dd8b                                                                                                                    
  +-com.taobao.arthas.agent.ArthasClassloader@17e023f0                                                                                                         
  +-sun.misc.Launcher$AppClassLoader@18b4aac2                                                                                                                  
    +-org.springframework.boot.loader.LaunchedURLClassLoader@7fad8c79                                                                                          
      +-com.alibaba.fastjson.util.ASMClassLoader@4be7162b                                                                                                      
      +-TomcatEmbeddedWebappClassLoader                                                                                                                        
          context: ROOT                                                                                                                                        
          delegate: true                                                                                                                                       
        ----------> Parent Classloader:                                                                                                                        
        org.springframework.boot.loader.LaunchedURLClassLoader@7fad8c79                                                                                        

Affect(row-cnt:7) cost in 23 ms.
  • -c: 执行表达式的 ClassLoader 的 hashcode,默认值是SystemClassLoader。
[arthas@1]$ ognl -c 7fad8c79 '@com.xx.actionlog.impl.ActionLogConfigApiImpl@DEFAULT_CLUSTER'
@String[default]

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK