Arthas原理-Watch命令的执行过程


前置流程

1、arthas 客户端,通过 命令行工具,启动了 arthas 终端

入口 com.taobao.arthas.client.TelnetConsole#process(java.lang.String[], java.awt.event.ActionListener)

2、目标 JVM 通过 agentmain 的方式,将 arthas 的核心代码注入到 jvm 里

入口: com.taobao.arthas.agent334.AgentBootstrap#agentmain

arthas-core agent 启动流程

1、解析参数,获取 arthas-core 的 jar 路径

若传入的 jar 路径不存在,则尝试去当前运行AgentBootstrap 的 classloader 路径下,获取 arthas-core.jar

若还加载不成功,则报错,启动失败

2、创建一个新的 classloader,新开一个线程

3、在新的线程里面,使用 classloader,通过反射的方式,去执行

com.taobao.arthas.core.server.ArthasBootstrap#getInstance(java.lang.instrument.Instrumentation, java.lang.String)

方法,获取 arthas 的 bootstrap 实例

4、 然后判断当前实例是否已经启动,若已经启动,则抛异常

arthas-core 核心启动流程

单例,实例化一个ArthasBootstrap 实例

构造函数中,执行以下逻辑:

0、初始化 fastjson:initFastjson()

1、初始化 Spy:initSpy()

使用 bootstrap Classloader,去加载 java.arthas.SpyAPI 类

若为加载到,则尝试从当前类的 codeSource 中的位置,去加载

若还加载失败,在抛异常

2、初始化 arthas 环境:initArthasEnvironment(args)

主要是根据参数,初始化一个ArthasEnvironment实例,略过,不细究

3、其他操作

  • 确保 arthas 的 output 目录存在
  • 初始化日志系统:使用 logback

4、增强 classloader:enhanceClassLoader()

通过配置,创建了一个com.alibaba.bytekit.asm.instrument.InstrumentTransformer 实例

给instrumentation 添加了类转换器

对类进行增强:

要么是 ClassLoader 这个类

要么是通过参数传入的类 set

PS:此处使用了 byteKit 类库工具,还需要进一步研究

5、初始化 bean:initBeans()

创建了resultViewResolver、historyManager

6、绑定服务:bind(Configure configure)

使用 cas 来确保只有一个进程能绑定成功

设置随机的 tcp 端口、http 端口

尝试获取被监听的 jvm 的应用名称(通过 spring.application.name 配置来)

6.1 根据上面的配置,创建TunnelClient 实例,并 start()启动

即,启动一个 webSocket 服务(基于 netty)

核心的 handler 是这个:TunnelClientSocketClientHandler(待分析)

6.2 根据上面的配置,再创建一个 Shell 服务

创建ShellServerImpl 实例:shellServer

启动一个 netty 的服务实例:workerGroup

给termServers 注册HttpTelnetTermServer、HttpTermServer(依赖 workerGroup)

将内置的命令处置器们:BuiltinCommandPack,注册到 termServer 的resolvers List 里

异步启动 shellServer

实际启动的服务,应该是com.taobao.arthas.core.shell.term.impl.TelnetTermServer#listen 这个

依赖了 termd-core

作用应该是处理输入字符的,具体不太明白

启动 http 的 session 的 manager

启动一个 http 的 api 的 handler

调用 java.arthas.SpyAPI#init 初始化 SpyAPI

7、创建一个周期调度的只有一个线程的线程池:executorService,并将其线程设置为 守护线程

至此,目标 JVM 被增强了的内容有:

画板

arthas-core 运行态结构

当接收到用户输入的 watch 命令时,系统的处置流程

1、ShellLineHandler 创建一个createJob,对应用户输入的 watch 命令

通过 com.taobao.arthas.core.shell.system.impl.JobControllerImpl#createJob,对用户输入的命令,进行解析,,解析出来 Command

流程入口,在 com.taobao.arthas.core.shell.system.impl.JobControllerImpl#createJob 中

包装为 com.taobao.arthas.core.shell.system.impl.ProcessImpl,该类的 run 里面,会去调用

com.taobao.arthas.core.server.ArthasBootstrap#execute,通过 SpyAPI 的方式,调用具体的增强方法

具体的命令,在目录com/taobao/arthas/core/command 下面

画板

增强命令的类图结构

画板


文章作者: 王利康
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 王利康 !
  目录