在k8s中查看使用 Arthas 查看 JAR 包源码的完整实战

在 Kubernetes 容器中使用 Arthas 查看 JAR 包源码的完整实战

作为一名 Java 开发者,你是否曾遇到过这样的困境:线上应用出了问题,但手头只有正在运行的 JAR 包,没有源码,无法快速定位逻辑?在 Kubernetes 环境下,甚至连容器内部都没有 curl 或 wget,如何破局?本文将详细记录一次在 K8s Pod 中利用 Arthas 反编译查看源码的完整过程,涵盖从环境准备、踩坑到最终胜利的所有细节。(文中所有敏感信息均已使用占位符替换)

一、背景与目标

我们的应用部署在 Kubernetes 集群中,镜像为基础 JDK 17 的精简镜像,内部没有 curl 工具。我们需要查看某个业务类的 process 方法源码,以排查数据转换的 bug。

目标 Pod:
my-app-deployment-7b9d8f6c4d-abc12,命名空间 my-namespace

目标类:
com.example.business.service.impl.MyService#process(com.example.common.model.DataEntity)

二、环境信息

  • Kubernetes 集群版本:v1.24+

  • Pod 内 JDK 版本:OpenJDK 17

  • Arthas 版本:4.3.1

  • 容器基础镜像:Alpine Linux(无 curl,但有 wget

三、操作步骤全记录

1. 确认 Pod 状态及命名空间

首先,列出命名空间 my-namespace 下的所有 Pod:

bash
[root@k8s-master-01 ~]# kubectl get pod -n my-namespace
NAME                                                   READY   STATUS    RESTARTS      AGE
connector-saas-5566cb95d-fpqjd                         1/1     Running   0             21m
my-app-deployment-7b9d8f6c4d-abc12                    1/1     Running   0             40m
another-service-689fc9f6bf-89v6f                      1/1     Running   0             42m
nfs-provisioner-8444644c9c-dgkwd                      1/1     Running   2 (24d ago)   25d
nginx-sss-s1-5c58fbb8f8-b27v2                   1/1     Running   0             37d
v-nginx-5c4df78469-9z796                             1/1     Running   0             36d

目标 Pod my-app-deployment-7b9d8f6c4d-abc12 正在运行。

2. 进入容器(踩坑点:忘记加命名空间)

最初尝试直接 exec

bash
[root@k8s-master-01 ~]# kubectl exec -it my-app-deployment-7b9d8f6c4d-abc12 -- /bin/bash
Error from server (NotFound): pods "my-app-deployment-7b9d8f6c4d-abc12" not found

原因:没有指定 -n my-namespace,kubectl 默认在 default 命名空间查找,自然找不到。

正确命令

bash
[root@k8s-master-01 ~]# kubectl exec -it my-app-deployment-7b9d8f6c4d-abc12 -n my-namespace -- /bin/sh

由于容器内没有 /bin/bash,使用 /bin/sh 成功进入。

3. 查看 Java 进程 PID

进入容器后,执行:

bash
/app # ps -ef | grep java
    1 root      0:00 /bin/sh -c # 将自定义 hosts 写入 /etc/hosts cat /etc/hosts.custom >> /etc/hosts java $JAVA_OPTS -jar /app/app.jar 
    8 root      2:16 java -Xms1536m -Xmx1536m -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m -XX:ReservedCodeCacheSize=128m -XX:MaxDirectMemorySize=256m -XX:+UseContainerSupport -jar /app/app.jar
  605 root      0:00 grep java

关键发现:

  • PID 1 是启动脚本的 shell 进程,不是 JVM

  • 真正的 JVM 进程 PID 是 8

  • 稍后 attach 时必须用 PID 8,而不是 1。

4. 下载 Arthas(容器内无 curl)

尝试直接用 curl 下载:

bash
/app # curl -O https://arthas.aliyun.com/arthas-boot.jar
/bin/sh: curl: not found

发现容器没有 curl,但幸运的是有 wget

bash
/app # wget --help
BusyBox v1.35.0 ... multi-call binary.

于是用 wget 下载:

bash
/app # wget https://arthas.aliyun.com/arthas-boot.jar
Connecting to arthas.aliyun.com (203.119.175.202:443)
saving to 'arthas-boot.jar'
arthas-boot.jar      100% |*******************************************************************************************************|  144k  0:00:00 ETA
'arthas-boot.jar' saved

5. 启动 Arthas(踩坑:错误地使用了 PID 1)

初始尝试 attach 到 PID 1:

bash
/app # java -jar arthas-boot.jar 1
[INFO] JAVA_HOME: /opt/openjdk-17
[INFO] arthas-boot version: 4.3.1
[INFO] Start download arthas from remote server: https://arthas.aliyun.com/download/4.3.1?mirror=aliyun
[INFO] File size: 16.29 MB, downloaded size: 11.27 MB, downloading ...
[INFO] Download arthas success.
[INFO] arthas home: /root/.arthas/lib/4.3.1/arthas
[INFO] Try to attach process 1
Picked up JAVA_TOOL_OPTIONS: 
[ERROR] Start arthas failed, exception stack trace: 
com.sun.tools.attach.AttachNotSupportedException: Unable to open socket file /proc/1/root/tmp/.java_pid1: target process 1 doesn't respond within 10500ms or HotSpot VM not loaded
...

报错原因:PID 1 不是 JVM 进程,无法 attach。

解决:使用正确 PID 8 重新启动:

bash
/app # java -jar arthas-boot.jar 8

这次成功,出现 [arthas@8]$ 提示符,表示已进入 Arthas 交互界面。

6. 使用 jad 反编译查看源码

6.1 直接查看整个类

bash
[arthas@8]$ jad --source-only com.example.business.service.impl.MyService

输出类完整源码(略)。

6.2 只查看特定方法(推荐)

我们想看 process 方法的实现:

bash
[arthas@8]$ jad --source-only com.example.business.service.impl.MyService process

如果该类只有一个 process 方法,直接输出该方法体。若有多个重载,Arthas 会列出所有重载签名,提示歧义。

6.3 处理方法重载(进阶)

如果提示 Found more than one method,可以先查看所有方法签名:

bash
[arthas@8]$ sm com.example.business.service.impl.MyService

找到目标方法的完整签名后,再使用精确匹配(用空格分隔方法名和参数类型,但参数类型只写简单类名或全限定名,且不能带括号):

bash
[arthas@8]$ jad --source-only com.example.business.service.impl.MyService process com.example.common.model.DataEntity

注意:这里没有 # 和括号,而是将方法名和参数类型用空格隔开。

6.4 如果上述仍不行,直接反编译全类并用 grep 过滤

bash
[arthas@8]$ jad --source-only com.example.business.service.impl.MyService > /tmp/class.java
[arthas@8]$ cat /tmp/class.java | grep -A 20 "process"

7. 输出源码保存到文件(便于外部查看)

在 Arthas 内部或直接在 shell 下,将反编译结果重定向:

bash
[arthas@8]$ jad --source-only com.example.business.service.impl.MyService process > /tmp/process.java

然后退出 Arthas(quit),从容器外使用 kubectl cp 将文件拷出:

bash
# 在宿主机执行
[root@k8s-master-01 ~]# kubectl cp my-namespace/my-app-deployment-7b9d8f6c4d-abc12:/tmp/process.java ./process.java

四、问题排查经验总结

 
 
常见问题 原因 解决方案
kubectl exec 报 NotFound 未指定命名空间 加上 -n <namespace>
curl: not found 镜像无 curl 尝试 wget 或 kubectl cp
Arthas attach 失败(目标进程不响应) 指定了错误的 PID(比如 shell 进程) 用 ps -ef 找出真正的 Java 进程 PID
jad 提示方法歧义 存在多个重载方法 用 sm 查看签名,或直接反编译全类手动查找
jad 命令带括号或 # 报错 Shell 解析特殊字符 方法参数应使用空格分隔,不加括号和 #

五、其他值得推荐的方法

  • 预先将 Arthas 打包进镜像:在 Dockerfile 中添加 RUN wget https://arthas.aliyun.com/arthas-boot.jar -O /opt/arthas/arthas-boot.jar,下次使用无需下载。

  • 使用 kubectl cp 上传:若容器内无 wget/curl,可在宿主机下载后 kubectl cp 传入。

  • 使用 kubectl debug 临时容器(K8s v1.25+)启动一个带工具的调试容器共享进程命名空间,更方便调试。

六、结语

经过一番波折,我们最终成功地在 K8s 容器中通过 Arthas 查看了目标 JAR 包的源码。整个过程的核心在于:

  1. 明确目标进程的 PID;

  2. 选择合适的工具下载方式;

  3. 正确使用 jad 命令的语法。

Arthas 的强大不仅限于反编译,还包括动态跟踪、方法执行监控等,是线上问题排查的利器。希望这篇实战记录能帮助你在类似场景下快速解决问题。


附:本文使用到的所有命令速查表

bash
# 进入 Pod
kubectl exec -it <pod> -n <namespace> -- /bin/sh

# 查看 Java 进程
ps -ef | grep java

# 下载 Arthas(有 wget)
wget https://arthas.aliyun.com/arthas-boot.jar

# 启动 Arthas(attach 到正确 PID)
java -jar arthas-boot.jar <PID>

# 反编译类
jad --source-only <类全限定名> [方法名] [参数类型...]

# 查看类的方法签名
sm <类全限定名>

# 复制文件到本地
kubectl cp <namespace>/<pod>:<容器内路径> <本地路径>
posted @ 2026-07-09 19:58  程序员鲜豪  阅读(8)  评论(0)    收藏  举报