Arthas 源码学习
一、从arthas-spring-boot-starter开始
官方提供的Arthas Spring Boot Starter,以maven依赖的方式启动了arthas,attach自身进程后常驻;
以starter包为切入点查看arthas是如何进行attach和执行命令等一系列操作的
1.1 starter的configuration拉起AttachArthasClassloader
starter中的ArthasConfiguration类,指定在配置开启时加载attach.ArthasAgent并加载其init方法
init方法内的主要逻辑为启动AttachArthasClassloader:
com.taobao.arthas.agent.attach.ArthasAgent#init
if (instrumentation == null) {
instrumentation = ByteBuddyAgent.install();
}
// 检查 arthasHome
if (arthasHome == null || arthasHome.trim().isEmpty()) {
// 解压出 arthasHome
URL coreJarUrl = this.getClass().getClassLoader().getResource("arthas-bin.zip");
if (coreJarUrl != null) {
File tempArthasDir = createTempDir();
ZipUtil.unpack(coreJarUrl.openStream(), tempArthasDir);
arthasHome = tempArthasDir.getAbsolutePath();
} else {
throw new IllegalArgumentException("can not getResources arthas-bin.zip from classloader: "
+ this.getClass().getClassLoader());
}
}
// find arthas-core.jar
File arthasCoreJarFile = new File(arthasHome, ARTHAS_CORE_JAR);
if (!arthasCoreJarFile.exists()) {
throw new IllegalStateException("can not find arthas-core.jar under arthasHome: " + arthasHome);
}
AttachArthasClassloader arthasClassLoader = new AttachArthasClassloader(
new URL[] { arthasCoreJarFile.toURI().toURL() });
/**
* <pre>
* ArthasBootstrap bootstrap = ArthasBootstrap.getInstance(inst);
* </pre>
*/
Class<?> bootstrapClass = arthasClassLoader.loadClass(ARTHAS_BOOTSTRAP);
Object bootstrap = bootstrapClass.getMethod(GET_INSTANCE, Instrumentation.class, Map.class).invoke(null,
instrumentation, configMap);
boolean isBind = (Boolean) bootstrapClass.getMethod(IS_BIND).invoke(bootstrap);
if (!isBind) {
String errorMsg = "Arthas server port binding failed! Please check $HOME/logs/arthas/arthas.log for more details.";
throw new RuntimeException(errorMsg);
}
解压arthas-bin.zip包后通过AttachArthasClassloader加载,可以看到对应属性中bootstrap类是com.taobao.arthas.core.server.ArthasBootstrap,方法是getInstance,跳转到core中的Bootstrap类:
对应getInstance方法调了构造方法ArthasBootstrap,到这里arthas-core模块才真正起起来:
其中最重要的流程是bind方法,启动了arthas server,关键逻辑在ShellServer的初始化: