文章目录
arthas-boot
该module 的代码只有3个类:
Bootstrap
启动类 Bootstrap ,开头的注解就是 alibaba 的 cli 中间件,和 picocli 蛮像。
arthas 在一些命令的执行需要有 JDK 命令的支持,以 ProcessUtils.select 为例,该方法实际上是要调用JAVA_HOME 下的 jps
jps -l
long pid = bootstrap.getPid();
// select pid
if (pid < 0) {
try {
pid = ProcessUtils.select(bootstrap.isVerbose(), telnetPortPid, bootstrap.getSelect());
} catch (InputMismatchException e) {
System.out.println("Please input an integer to select pid.");
System.exit(1);
}
if (pid < 0) {
System.out.println("Please select an available pid.");
System.exit(1);
}
}
选择 pid 后下载相关依赖:
后面就是启动关键模块 arthas-core
也就是说又启动了一个java进程:
这就理解了 arthas 提升要用 stop 命令来推出,而不是关闭当前命名窗口,它是个多进程应用。
之后构建 ProcessBuilder 执行命令:
// "${JAVA_HOME}"/bin/java \
// ${opts} \
// -jar "${arthas_lib_dir}/arthas-core.jar" \
// -pid ${TARGET_PID} \
// -target-ip ${TARGET_IP} \
// -telnet-port ${TELNET_PORT} \
// -http-port ${HTTP_PORT} \
// -core "${arthas_lib_dir}/arthas-core.jar" \
// -agent "${arthas_lib_dir}/arthas-agent.jar"
并将进程的标准输出、标准错误进行重定向:
ProcessBuilder pb = new ProcessBuilder(command);
// https://github.com/alibaba/arthas/issues/2166
pb.environment().put("JAVA_TOOL_OPTIONS", "");
try {
final Process proc = pb.start();
Thread redirectStdout = new Thread(new Runnable() {
@Override
public void run() {
InputStream inputStream = proc.getInputStream();
try {
IOUtils.copy(inputStream, System.out);
} catch (IOException e) {
IOUtils.close(inputStream);
}
}
});
Thread redirectStderr = new Thread(new Runnable() {
@Override
public void run() {
InputStream inputStream = proc.getErrorStream();
try {
IOUtils.copy(inputStream, System.err);
} catch (IOException e) {
IOUtils.close(inputStream);
}
}
});
redirectStdout.start();
redirectStderr.start();
redirectStdout.join();
redirectStderr.join();
int exitValue = proc.exitValue();
if (exitValue != 0) {
AnsiLog.error("attach fail, targetPid: " + targetPid);
System.exit(1);
}
最终看到这个: