唯一安全的jvm调试绑定方式是address=127.0.0.1:5005,因其仅响应本机回环连接;ssh隧道必须用ssh -l 5005:localhost:5005确保逻辑地址对齐;vscode中hostname必须设为localhost,且需用nc或telnet验证隧道连通性。

address=127.0.0.1:5005 是唯一安全的 JVM 绑定方式
JDWP 协议本身不带认证和加密,address=*:5005 或 address=0.0.0.0:5005 等同于把调试后门直接贴在公网门口。只要知道 IP 和端口,攻击者就能 attach 进程、执行任意代码、dump 内存——这不是“可能被利用”,而是“必然被利用”。
正确做法只有一条:-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=127.0.0.1:5005。这个参数强制 JVM 只响应本机回环地址上的连接,外部流量根本无法抵达调试端口。
- 不要用
localhost替代127.0.0.1:某些 JVM 版本或容器环境下,localhost可能解析为 IPv6 地址(::1),导致监听失败或行为不一致 - 端口号可自定义(如 5006),但必须与后续 SSH 隧道、VSCode 配置严格一致
- 若应用跑在 Docker 容器里,JVM 参数仍需写
127.0.0.1:5005;容器启动时无需-p 5005:5005,因为端口只对容器内 localhost 有效
ssh -L 5005:localhost:5005 是唯一匹配的隧道命令
SSH 隧道不是“把远程端口搬过来”,而是建立一条加密通道,让本地发往 localhost:5005 的流量,经由 SSH 加密后,在远程服务器上以“从 localhost 发起”的身份访问目标端口。这就要求两端逻辑地址完全对齐。
常见错误是写成 ssh -L 5005:remote-host-ip:5005 —— 此时 SSH 尝试从远程主机的网卡 IP 去连 5005,但 JVM 只监听 127.0.0.1,根本收不到请求。
- 正确命令:
ssh -L 5005:localhost:5005 user@remote-server - 如果远程服务实际监听的是
127.0.0.1:5006,那就得改成ssh -L 5005:localhost:5006,本地 VSCode 连localhost:5005 - 隧道断开后不会自动重连,生产环境建议用
autossh或 systemd service 管理,而非依赖终端前台进程
launch.json 中 hostName 必须填 localhost
launch.json 里的 hostName 字段不是让你填远程服务器 IP,它是告诉 VSCode:“去哪个地址连调试端口”。既然你用了 SSH 隧道,那目标就是本地监听的端口,所以必须是 localhost 或 127.0.0.1。
Java JDK 25 来自 OpenJDK 官方归档,版本为 JDK 25,本条下载地址已指向官方 Windows x64 zip 安装包直链,适合调试旧项目或兼容旧版 Java 运行环境。
填错 hostName 的后果不是“连不上”,而是 VSCode 直接绕过隧道,尝试走公网直连远程 IP:5005——这既失败(防火墙/安全组拦截),又危险(暴露调试入口)。
- 典型配置片段:
{ "type": "java", "name": "Remote Debug", "request": "attach", "hostName": "localhost", "port": 5005 } - 如果改了本地隧道端口(比如用
ssh -L 5006:localhost:5005),这里port就得同步改成5006 - 不要依赖
sourceFileMap自动推导路径;务必显式设置"remoteRoot": "/path/in/server"和"localRoot": "${workspaceFolder}",否则断点永远不命中
调试前必须验证隧道连通性,而不是直接点 F5
90% 的“连不上”问题,根源不在配置,而在隧道根本没生效。VSCode 不会告诉你“SSH 隧道未建立”,它只会安静地超时失败。
最简验证方式就是绕过所有工具,用系统命令确认链路是否打通:
- 运行
nc -zv localhost 5005(macOS/Linux)或telnet localhost 5005(Windows):能连上说明隧道已就绪 - 登录远程服务器,检查 JVM 日志是否有
Listening for transport dt_socket at address: 127.0.0.1:5005 - 在远程服务器执行
ss -tln | grep :5005,输出中应含127.0.0.1:5005,且状态为LISTEN - 如果用的是 Kubernetes Pod 或容器编排环境,先
kubectl exec -it <pod> -- sh</pod>进入容器,再查监听状态,避免误判宿主机网络
真正容易被忽略的,是 JVM 绑定地址与 SSH 隧道目标地址之间那种隐式的“逻辑 localhost”一致性——它们不是字符串匹配,而是网络栈层面的回环语义对齐。差这一层理解,配置写得再全也没用。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










