arthas线上不停机修改bug

安装arthas

shell 复制代码
wget https://alibaba.github.io/arthas/arthas-boot.jar

启动:

java -jar arthas-boot.jar

启动失败

使用jps也没查到对应的进程

发生错误信息

使用进程id启动,报错

进程id查看使用命令:

ps -ef | grep java

详情:

shell 复制代码
[INFO] JAVA_HOME: /usr/local/java/jdk17
[INFO] arthas-boot version: 4.0.5
[INFO] Start download arthas from remote server: https://arthas.aliyun.com/download/4.0.5?mirror=aliyun
[INFO] Download arthas success.
[INFO] arthas home: /home/appadmin/.arthas/lib/4.0.5/arthas
[INFO] Try to attach process 4004020
Picked up JAVA_TOOL_OPTIONS: 
[ERROR] Start arthas failed, exception stack trace: 
java.io.IOException: Operation not permitted
        at jdk.attach/sun.tools.attach.VirtualMachineImpl.sendQuitTo(Native Method)
        at jdk.attach/sun.tools.attach.VirtualMachineImpl.<init>(VirtualMachineImpl.java:82)
        at jdk.attach/sun.tools.attach.AttachProviderImpl.attachVirtualMachine(AttachProviderImpl.java:58)
        at jdk.attach/com.sun.tools.attach.VirtualMachine.attach(VirtualMachine.java:207)
        at com.taobao.arthas.core.Arthas.attachAgent(Arthas.java:100)
        at com.taobao.arthas.core.Arthas.<init>(Arthas.java:27)
        at com.taobao.arthas.core.Arthas.main(Arthas.java:161)
[INFO] Attach process 4004020 success.
[INFO] arthas-client connect 127.0.0.1 3658
Connect to telnet server error: 127.0.0.1 3658
java.net.ConnectException: Connection refused
        at java.base/sun.nio.ch.Net.pollConnect(Native Method)
        at java.base/sun.nio.ch.Net.pollConnectNow(Net.java:672)
        at java.base/sun.nio.ch.NioSocketImpl.timedFinishConnect(NioSocketImpl.java:547)
        at java.base/sun.nio.ch.NioSocketImpl.connect(NioSocketImpl.java:602)
        at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:327)
        at java.base/java.net.Socket.connect(Socket.java:633)
        at org.apache.commons.net.SocketClient.connect(SocketClient.java:188)
        at org.apache.commons.net.SocketClient.connect(SocketClient.java:209)
        at com.taobao.arthas.client.TelnetConsole.process(TelnetConsole.java:306)
        at com.taobao.arthas.client.TelnetConsole.main(TelnetConsole.java:166)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:568)
        at com.taobao.arthas.boot.Bootstrap.main(Bootstrap.java:634)
Usage: arthas-client [--help] [-c <value>] [-f <value>] [-w <value>] [-t
       <value>] [-h <value>] [target-ip] [port]

Arthas Telnet Client

查询日志告知是 : Arthas 在尝试附加到目标 Java 进程(PID 为 4004020)时遇到了问题,并且 Telnet 客户端无法连接到 Arthas Server。

  • 误发生在 sun.tools.attach.VirtualMachineImpl.sendQuitTo(Native Method) 中。
  • 原因分析:
    1. 权限不足:
      • 当前用户(appadmin)没有权限访问目标进程(PID 4004020)。
      • 如果目标进程由 root 用户启动,而你以普通用户运行 Arthas,则会导致权限问题。

使用ps -ef | grep java查看java进程

检查权限

查看目标进程的用户信息:

shell 复制代码
ps -ef | grep 4004020

输出如下:

目标进程由 root 用户启动,而你以普通用户(appadmin)运行 Arthas,因此权限不足

解决方式:

使用下面命令尝试:

shell 复制代码
sudo java -jar arthas-boot.jar 4004020

结果报错:

查询报错原因是:在使用 sudo 提升权限后,系统无法找到 java 命令。

错误原因分析

(1) sudo 的环境变量问题
  • 当你直接运行 java -jar arthas-boot.jar 时,java 是通过当前用户的环境变量(如 PATH)找到的。
  • 使用 sudo 后,环境变量会切换到 root 用户的环境变量,而 root 用户的 PATH 中可能没有包含 java 的路径。

2. 解决方案

(1) 明确指定 java 的完整路径
  • 直接使用 java 的绝对路径来运行命令,避免依赖 PATH 环境变量。

    shell 复制代码
    sudo /usr/local/java/jdk17/bin/java -jar arthas-boot.jar 4004020

可以看到启动成功:

反编译错误的代码位置

接下来使用jad命令 将需要更改的文件先进行反编译,保存下来 ,编译器修改放到tmp目录下

shell 复制代码
 jad --source-only org.mili.order.domain.bo.OrderServiceCompleteVerifyBo > /tmp/OrderServiceCompleteVerifyBo.java

将 OrderServiceCompleteVerifyBo.java下载下来后修改错误的地方(我这里是指删了一个NotNull的一个注解)

查看hash码(类加载器的)

shell 复制代码
sc -d org.mili.order.domain.bo.OrderServiceCompleteVerifyBo | grep classLoaderHash

返回如下:

shell 复制代码
 classLoaderHash   7a765367

将修改后的文件放到tmp/zss/ 目录下,MC命令 用指定的classloader类加载器的hash码重新将类在内存中编译

shell 复制代码
 mc -c 7a765367 /tmp/zss/OrderServiceCompleteVerifyBo.java -d /tmp/zss

替换字节码文件

redefine命令 将编译后的类加载到JVM

下面是上边编译后的.class文件地址

shell 复制代码
redefine /tmp/zss/org/mili/order/domain/bo/OrderServiceCompleteVerifyBo.class

如下图

关闭arthas,测试即可

shell 复制代码
stop

操作记录如下图片

相关推荐
ac.char1 小时前
编辑 JAR 包内嵌套的 TXT 文件(Vim 操作)
java·pycharm·vim·jar
TomcatLikeYou3 小时前
blender4.5 使用外部IDE(pycharm)编辑脚本(bpy)实践指南
服务器·pycharm·php·blender
路由侠内网穿透.3 小时前
本地部署集成全能平台 Team.IDE 并实现外部访问
运维·服务器·数据库·ide·远程工作
IDOlaoluo5 小时前
FindBugs-IDEA-1.0.1.zip安装使用教程(IntelliJ IDEA插件手动安装查Bug)
java·bug·intellij-idea
Ocean_hys5 小时前
改bug创建分支的流程
bug
better112012 小时前
IDE热键冲突的解决
ide
JosieBook16 小时前
【软件安装】在 Visual Studio 2022 中安装 RDLC 报表插件的详细教程
ide·visual studio
gfdgd xi16 小时前
GXDE For deepin 25:deepin25 能用上 GXDE 了!
linux·运维·python·ubuntu·架构·bug·deepin
qc175218 小时前
PyCharm + 远程调试路径映射总结(以 diffusers 为例)
ide·python·pycharm
哲此一生98419 小时前
Vscode中选择Conda环境
ide·vscode·编辑器