安装arthas
wget https://alibaba.github.io/arthas/arthas-boot.jar
启动:
java -jar arthas-boot.jar
启动失败
使用jps也没查到对应的进程
发生错误信息
使用进程id启动,报错
进程id查看使用命令:
ps -ef | grep java
详情:
[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)
中。 - 原因分析:
- 权限不足:
- 当前用户(
appadmin
)没有权限访问目标进程(PID4004020
)。 - 如果目标进程由
root
用户启动,而你以普通用户运行 Arthas,则会导致权限问题。
- 当前用户(
- 权限不足:
使用ps -ef | grep java
查看java进程
检查权限
查看目标进程的用户信息:
ps -ef | grep 4004020
输出如下:
目标进程由 root
用户启动,而你以普通用户(appadmin
)运行 Arthas,因此权限不足
解决方式:
使用下面命令尝试:
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
环境变量。sudo /usr/local/java/jdk17/bin/java -jar arthas-boot.jar 4004020
可以看到启动成功:
反编译错误的代码位置
接下来使用jad命令
将需要更改的文件先进行反编译,保存下来 ,编译器修改放到tmp目录下
jad --source-only org.mili.order.domain.bo.OrderServiceCompleteVerifyBo > /tmp/OrderServiceCompleteVerifyBo.java
将 OrderServiceCompleteVerifyBo.java下载下来后修改错误的地方(我这里是指删了一个NotNull的一个注解)
查看hash码(类加载器的)
sc -d org.mili.order.domain.bo.OrderServiceCompleteVerifyBo | grep classLoaderHash
返回如下:
classLoaderHash 7a765367
将修改后的文件放到tmp/zss/ 目录下,MC命令
用指定的classloader类加载器的hash码重新将类在内存中编译
mc -c 7a765367 /tmp/zss/OrderServiceCompleteVerifyBo.java -d /tmp/zss
替换字节码文件
redefine命令
将编译后的类加载到JVM
下面是上边编译后的.class文件地址
redefine /tmp/zss/org/mili/order/domain/bo/OrderServiceCompleteVerifyBo.class
如下图
关闭arthas,测试即可
stop
操作记录如下图片