BindException: Address already in use表明端口被占用,需先通过netstat或lsof查PID,再用tasklist或ps定位进程;常见占用源包括Docker、IDE内嵌Tomcat、重复启动的Spring Boot实例等。

当 Java 网络程序启动时抛出 BindException: Address already in use,说明目标端口已被其他进程占用。这不是代码逻辑错误,而是系统资源冲突,排查需结合 Java 异常信息和操作系统工具定位真实占用者。
看异常堆栈,确认绑定端口和地址
异常中通常包含具体端口号和绑定地址,例如:
java.net.BindException: Address already in use: bind
at sun.nio.ch.Net.bind0(Native Method)
at sun.nio.ch.Net.bind(Net.java:461)
at sun.nio.ch.Net.bind(Net.java:453)
at sun.nio.ch.ServerSocketChannelImpl.bind(ServerSocketChannelImpl.java:222)
at sun.nio.ch.ServerSocketAdaptor.bind(ServerSocketAdaptor.java:74)
at java.net.ServerSocket.bind(ServerSocket.java:376)
重点提取:bind 调用的目标端口(如 8080)、是否绑定了特定 IP(如 127.0.0.1:8080 或 0.0.0.0:8080)。Java 代码中检查 ServerSocket 或 ServerSocketChannel 的 bind() 参数,确认你试图监听的端口值。
立即学习“Java免费学习笔记(深入)”;
用系统命令查谁占了这个端口
不同系统命令略有差异,但目标一致:找出监听该端口的进程 ID(PID)和程序名。
-
Linux / macOS:
lsof -i :8080或netstat -tuln | grep :8080(macOS 需先安装netstat工具) -
Windows:
netstat -ano | findstr :8080,再用tasklist | findstr "12345"(12345 是上一步查到的 PID)
注意:若只查到 java 进程,可能是你自己的旧实例没关干净;若看到 node、python、Docker 或 nginx,说明是其他服务占用了端口。
检查 Java 应用自身是否重复启动
开发中常见问题:IDE(如 IntelliJ)多次点击运行,或终端里手动执行 java -jar xxx.jar 没杀掉前一个进程。可这样验证:
- 运行
jps -l查看所有 Java 进程及其主类,找是否有重复的 jar 或相同类名 - 检查日志输出时间戳,确认是否多个实例同时在打印启动日志
- 临时改用非常规端口(如 8081)测试——如果能启动,基本锁定是端口冲突而非代码问题
补充技巧:避免重启后仍报错
有时 kill 掉进程后立即重试仍报 BindException,因为端口处于 TIME_WAIT 状态(尤其 Linux 默认持续 60 秒)。解决方式包括:
- 等几十秒再试(最稳妥)
- Java 侧设置 socket 选项(仅适用于
ServerSocket):serverSocket.setReuseAddress(true),允许绑定处于 TIME_WAIT 的端口(注意:不解决真正被占用的问题,仅缓解重试延迟) - 开发环境可配置应用自动选可用端口(如 Spring Boot 的
server.port=0),启动后从日志读取实际端口



















