# Arthas运行原理
jdk1.5增加了java.lang.instrument,提供底层组件的访问能力,要求在运行前利用命令行或系统参数设置代理类,vm启动后,初始化
- premain函数
- 打包,制定premain-class
- 使用-javaagent启动
jdk1.6后,增加agentmain函数,之后通过addTransformer retransformclasses redefineClasses等对字节码增加
Jvmti(JVM Tool Interface)native接口,提供debug与profiler能力,实现调试器和其它运行态分析工具的基础,instrument就是对它的封装
动态attach步骤 VirtualMachine.attach(pid)
public static void agentmain(String args, Instrumentation inst) throws Exception
{
System.out.println("Args:" + args);
}
public static void premain(String args, Instrumentation inst) throws Exception
{
System.out.println("Pre Args:" + args);
Class[] classes = inst.getAllLoadedClasses();
for (Class clazz : classes)
{
System.out.println(clazz.getName());
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
- 加载libattach.so
- 创建attach_pid文件
- 发送sigquit信息
- jvm创建一个路径为/tmp/.java_pid的unix socket
- 建立连接
想要Arthas代码与应用的代码可同时获取到JMX等系统级的API,同时两者之间的代码是完全隔离的, ArthasClassLoader与AppClassLoader就必须共用同一个parent:ExtClassLoader,且两者要互相分属不同的ClassLoader
// Arthas源码:
public class ArthasClassloader extends URLClassLoader {
public ArthasClassloader(URL[] urls) {
super(urls, ClassLoader.getSystemClassLoader().getParent());
}
}
1
2
3
4
5
6
2
3
4
5
6
arthas-spy
Arthas启动时,Arthas会把spyJar添加到目标应用的BootstrapClassLoader的搜索路径中,这样不管是Arthas还是目标应用,他们加载的都是同一个SpyAPI
解析参数
Bootstrap bootstrap = new Bootstrap(); CLI cli = CLIConfigurator.define(Bootstrap.class); CommandLine commandLine = cli.parse(Arrays.asList(args)); CLIConfigurator.inject(commandLine, bootstrap);
1
2
3
4通过反向启动字符客户端
URLClassLoader classLoader = new URLClassLoader(new URL[]{new File(arthasHomeDir, "arthas-client.jar").toURL().toURL()}); Class<?> telnetConsoleClass = classLoader.loadClass("com.taobao.arthas.client.TelnetConsole"); Method mainMethod = telnetConsoleClas.getMethod("main", String[].class);
1
2
3# https://www.jianshu.com/p/0771646f3f25