Arthas stop 命令详解:优雅关闭诊断服务、断开全部客户端并重置增强类
【免费下载链接】arthasAlibaba Java Diagnostic Tool Arthas/Alibaba Java诊断利器Arthas项目地址: https://gitcode.com/gh_mirrors/ar/arthas
Arthas 是一款 Alibaba 开源的 Java 在线诊断工具,允许开发者在生产环境不重启应用的情况下实时排查问题。stop命令是 Arthas 中最具"全局影响力"的关闭指令:它用于终止整个 Arthas 服务端,所有连接到该服务端的 Arthas 客户端会全部退出。本文以 site/docs/en/doc/stop.md 为主体,结合仓库中的命令实现与引导类源码,深入讲解stop命令的功能、底层执行流程及其与reset、redefine/retransform的关系,帮助你安全、正确地关闭 Arthas 诊断会话。
stop 命令的功能概述
根据官方文档,stop命令的核心作用是:
terminates the Arthas server, all the Arthas clients connecting to this server will be disconnected.(终止 Arthas 服务端,所有连接到该服务端的 Arthas 客户端都将断开连接。)
也就是说,stop并不是简单地退出当前终端会话,而是对整个 Arthas 服务端执行关停操作。服务端关闭后,通过 telnet、WebSocket(Web Console)等渠道连接上来的所有 Arthas 客户端会话都会被一并销毁。
同时,官方文档(中文版见 site/docs/doc/stop.md)特别强调了一条关键提示:
关闭 Arthas 服务器之前,会重置掉所有做过的增强类。但是用 redefine 和 retransform 重加载的类内容不会被重置。
这条提示道出了stop与普通退出命令的本质区别:关闭服务端之前会自动执行一次全局类增强重置,但通过redefine/retransform直接重定义字节码的类内容则保留不变。
stop 命令的适用场景
Arthas 的所有诊断命令(如watch、trace、stack、monitor等)本质上都是通过字节码注入(byte-code-injection)在目标类中织入切面逻辑来实现监控与统计的。在官方命令总览文档 site/docs/en/doc/commands.md 中明确指出:
commands here are taking advantage of byte-code-injection... remember to remove the injected code by
stoporreset. (这些命令利用了字节码注入技术……记得使用stop或reset移除注入的代码。)
因此,stop的典型适用场景包括:
- 排查完成后的收尾:在线诊断任务结束,需要一次性清除所有增强效果、断开所有客户端,并将目标应用恢复到未诊断状态;
- 关闭 Arthas 服务端进程:不再需要 Arthas 监听端口与后台服务,彻底关停服务端;
- 批量会话管理:存在多个客户端连接时,通过一条
stop命令统一断开所有会话,而不必逐一执行退出操作。
如何在 Arthas 中使用 stop
在 Arthas 交互式控制台中直接输入stop并回车即可,无需任何参数:
$ stop Resetting all enhanced classes ... Affect(class count: 12 , method count: 20) cost in 42 ms, listenerId: 0 Arthas Server is going to shutdown...命令执行后,当前控制台会退出,其余所有连接到该服务端的客户端也会同时断开。从源码看,stop命令被定义为无参命令,声明如下(见 StopCommand.java):
@Name("stop") @Summary("Stop/Shutdown Arthas server and exit the console.") public class StopCommand extends AnnotatedCommand {@Summary注释明确了两层语义:关闭/停止 Arthas 服务端(Stop/Shutdown Arthas server)以及退出控制台(exit the console)。
stop 的底层执行流程(源码级解析)
stop命令的处理逻辑集中在StopCommand.shutdown(CommandProcess process)方法中(见 StopCommand.java),其执行流程分为"重置增强类 → 发送关停消息 → 销毁服务端"三个步骤:
第一步:重置所有增强类(reset)
process.appendResult(new MessageModel("Resetting all enhanced classes ...")); EnhancerAffect enhancerAffect = arthasBootstrap.reset(); process.appendResult(new ResetModel(enhancerAffect));在执行关停动作之前,命令首先向客户端输出Resetting all enhanced classes ...提示,随后调用ArthasBootstrap.reset()执行全局增强重置,并把重置结果以ResetModel的形式回显(包含受影响的类数量、方法数量与耗时统计)。这解释了我们在控制台看到的Affect(class count: ... , method count: ...)输出。
reset()的底层实现位于 ArthasBootstrap.java:
public EnhancerAffect reset() throws UnmodifiableClassException { return Enhancer.reset(this.instrumentation, new WildcardMatcher("*")); }它借助java.lang.instrument的instrumentation机制,以通配符*匹配目标应用中所有被增强的类并逐一还原字节码。这正是文档所强调的"关闭服务器之前会重置掉所有做过的增强类"的源码依据——stop内部复用了与reset命令相同的增强还原逻辑。
第二步:发送关停消息并结束当前进程
process.appendResult(new ShutdownModel(true, "Arthas Server is going to shutdown..."));重置完成后,命令构造ShutdownModel向客户端广播Arthas Server is going to shutdown...消息,然后调用process.end()结束当前命令处理流程。ShutdownModel会通知所有会话准备退出,这也是所有客户端同时断开的通信基础。
第三步:销毁服务端(destroy)
} finally { process.end(); arthasBootstrap.destroy(); }无论上述步骤是否成功,finally块都会调用ArthasBootstrap.destroy()对服务端做最终清理。从 ArthasBootstrap.java 的destroy()实现可以看到,它负责依次释放 Arthas 的各类资源:
- 关闭 MCP 服务(
arthasMcpBootstrap.shutdown()),避免停止后残留调度线程导致ArthasClassLoader无法回收; - 关闭 shell 服务端(
shellServer.close())与会话管理器(sessionManager.close()); - 停止 HTTP 会话管理器(
httpSessionManager.stop())、取消定时器(timer.cancel()); - 停止 Tunnel 客户端(
tunnelClient.stop()); - 关闭并销毁线程池(
executorService.shutdownNow())与增强转换器(transformerManager.destroy()); - 移除类加载器相关的字节码转换器(
classLoaderInstrumentTransformer); - 清理
Spy类中的引用(cleanUpSpyReference())、关闭 Netty 工作线程组、销毁用户统计(UserStatUtil.destroy()); - 移除 JVM 关闭钩子(shutdown hook),并在跨 mount namespace 场景下清理临时 Arthas home 目录。
从源码结构看,stop并不是简单的"断开连接",而是一整套完整的服务端生命周期收尾流程,目标是让注入的增强全部还原、占用的资源全部释放,使目标 JVM 恢复到接近未安装 Arthas 的状态。
stop 与 reset、redefine / retransform 的关系
理解stop的关键在于区分它与其他命令在"类状态"处理上的差异:
| 命令 | 对已增强类的处理 | 对重新加载类内容的处理 | 对服务端的影响 |
|---|---|---|---|
stop | 自动重置所有增强类(与reset等价) | redefine / retransform 重新加载的类内容不会被重置 | 终止整个服务端,断开所有客户端 |
reset | 重置所有增强类 | 同上 | 不关闭服务端,会话继续可用 |
redefine/retransform | 直接重定义/重转换目标类字节码 | 属于"永久性"类内容变更 | 不涉及服务端生命周期 |
这里需要特别强调官方文档的 tip:使用redefine或retransform命令重加载的类内容不会被stop重置。其原因可以从实现层面理解:reset只负责还原通过字节码注入(enhancement)方式产生的增强,而redefine/retransform是对类字节码本身的直接重定义,其效果不归属于"增强"范畴,因此不会在关停时被自动还原。如果你的线上排查过程中用到了这两个命令,且希望在关闭 Arthas 后彻底恢复原类字节码,需要在关停之前自行评估并手动恢复。
使用 stop 的注意事项
stop是服务端级操作:它会关闭 Arthas 服务端并断开所有客户端会话,不只是当前终端。请确认没有其他正在使用的会话,再执行该命令。- 增强类会被自动重置:正常通过
watch、trace等命令注入的增强会在关停前被自动清除,一般无需担心增强残留;这也是官方建议在排查结束后使用stop或reset清理注入代码的原因。 - redefine / retransform 的结果不会被重置:这两类命令造成的类内容变更在
stop后依然保留,若需还原需提前处理。 - 执行后服务端不可再用:
stop之后 Arthas 服务端进程被销毁,需要重新诊断时必须重新启动 Arthas(参考 start-arthas.md),再建立新的客户端连接。
延伸阅读
- stop 命令英文文档 与 stop 命令中文文档:本文的直接依据;
- reset 命令文档:了解手动重置增强类的用法;
- redefine 命令文档 与 retransform 命令文档:理解这两类不受重置影响的命令;
- 命令总览:了解全部 Arthas 命令及其与字节码注入的关系;
- StopCommand.java:
stop命令的入口实现; - ArthasBootstrap.java:
reset()与destroy()的完整服务端清理逻辑。
【免费下载链接】arthasAlibaba Java Diagnostic Tool Arthas/Alibaba Java诊断利器Arthas项目地址: https://gitcode.com/gh_mirrors/ar/arthas
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考