答案是用户不匹配:执行jstack的用户必须与java进程启动用户完全一致,可通过ps -o user= -p pid确认启动用户,再用sudo -u $user jstack $pid解决。

jstack 报 “well-known file is not secure” 就是因为用户不匹配,不是权限不够、不是路径不对、也不是 JDK 版本问题——核心就一条:执行 jstack 的用户必须和目标 Java 进程的启动用户完全一致。
怎么确认 Java 进程是谁启动的
别猜,直接查。用 ps 看第三列(UID 对应用户名):
-
ps -eo pid,user,comm,args | grep java—— 显示所有 java 进程的 PID、用户、命令名和完整参数 - 或者精准查某个 PID:
ps -o user= -p 12345(只输出用户名,无头无尾,方便脚本调用) - 注意:
pgrep -u appuser -f myapp.jar可以反向验证——指定用户 + 关键字,看是否能搜到该进程
为什么不能直接 sudo jstack
sudo jstack 12345 表面看是“提权”,但实际触发的是 root 用户去访问 /tmp/.java_pid12345,而这个文件是 appuser 启动 JVM 时创建的,属主是 appuser。jstack 内部会校验:当前 UID 是否等于该临时文件的 UID。不等就拒接,报错里写的 file should be owned by the current user (which is 0) but is owned by 9001 就是这个意思。
-
-F强制模式在这里无效,它绕不过底层文件属主检查 -
su -c "jstack 12345" appuser是可行的,但更推荐sudo -u appuser jstack 12345 - 如果目标用户没 shell(比如
nologin),需先确认该用户是否允许执行jstack(路径在$JAVA_HOME/bin/jstack,通常可执行)
Arthas 同样卡在用户匹配上
Arthas 的 arthas-boot.jar 底层也是 attach 到目标 JVM,依赖 /proc/<pid>/</pid> 和 /tmp/.java_pid<pid></pid>,所以同样受用户隔离限制。
- 容器内运行 Arthas:必须确保
docker exec进入后,当前 shell 用户与 Java 进程 UID 一致;否则 attach 失败报No such process或Unable to open socket file - K8s 场景下,除了
securityContext.capabilities.add: [SYS_PTRACE],还得保证 initContainer 或主容器以正确 UID 启动(比如runAsUser: 1001),否则 Arthas 启动时看到的进程列表为空 - 一个快速验证法:
sudo -u appuser ls -l /proc/12345/fd/—— 如果能看到 fd 列表,说明用户匹配成功,attach 工具大概率也能过
真正容易被忽略的点是:JVM 启动时的用户,和你登录服务器的用户,和容器 runtime 的用户,三者未必统一。诊断工具失败的第一反应不该是“重装 JDK”或“加 chmod”,而是立刻查 UID 对齐——这是 Linux 上 Java 诊断最硬的一道坎。











