前置流程
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 下面