下面是遇到的 Address already in use 是每一位后端开发者都必然会遇到的经典问题。将这次的调试经历写成一篇博客,不仅能加深您自己的理解,也能帮助无数后来者快速解决问题。
下面是为您精心撰写的技术博客。
Spring Boot 启动失败?解密 Address already in use 的“幕后真凶”
“代码没动,怎么突然就启动不了了?”
这或许是每个 Spring Boot 开发者都曾发出的灵魂拷问。你满怀信心地点击 IDE (Integrated Development Environment, 集成开发环境) 中的运行按钮,期望看到熟悉的启动日志,结果却被一盆冷水浇下——控制台打印出一长串红色的错误堆栈,最后以一段令人沮丧的 APPLICATION FAILED TO START 告终。
如果你仔细观察日志,很可能会发现一个“老朋友”:java.net.BindException: Address already in use。
本文将带你深入分析这个 Spring Boot 启动时最常见的“拦路虎”,通过解读真实的启动日志,教你如何像侦探一样,快速定位并“干掉”那个占用你端口的“幕后真凶”。
案发现场:一份典型的失败日志
一切都从一次看似正常的应用启动开始。然而,日志在打印到 Starting ProtocolHandler ["http-nio-8087"] 之后,风云突变:
2025-09-01 18:57:31.254 ERROR 4445 --- [main] o.a.c.util.LifecycleBase : Failed to start component [Connector[HTTP/1.1-8087]]
org.apache.catalina.LifecycleException: Protocol handler start failed
...
Caused by: java.net.BindException: Address already in use
...
最后,Spring Boot 给出了非常友好的“尸检报告”:
***************************
APPLICATION FAILED TO START
***************************
Description:
The Tomcat connector configured to listen on port 8087 failed to start. The port may already be in use or the connector may be misconfigured.
Action:
Verify the connector's configuration, identify and stop any process that's listening on port 8087, or configure this application to listen on another port.
探寻根源:端口被占用的本质
这份日志虽然长,但核心信息却异常清晰:
Failed to start component [Connector[HTTP/1.1-8087]]: Spring Boot 内嵌的 Tomcat Web 服务器,在尝试启动并监听8087端口时失败了。Caused by: java.net.BindException: Address already in use: 这是问题的根本原因。“地址已被占用”是一个底层的网络异常,意味着操作系统告诉你的 Java 程序:“你想租用8087这个‘门牌号’来提供服务,但对不起,这个‘门牌号’已经被别人先租走了。”
那么,这个“别人”是谁呢?
在开发环境中,99% 的情况下,这个“别人”就是上一次未能被正常关闭的、你自己启动的同一个应用程序!
这通常发生在:
- 你在 IDE 中点击了“停止”按钮,但由于某些原因(比如后台线程、数据库连接池未能正常关闭),Java 进程没有完全退出。
- 你直接关闭了 IDE,但后台的 Java 进程变成了“孤儿进程”,仍在默默地占用着端口。
- 你同时打开了多个项目,其中一个已经占用了这个端口。
解决方案:找到并终止“霸占者”
既然知道了问题所在,我们的任务就很明确了:找到那个占用 8087 端口的进程,并强制它“退租”。
在 macOS 或 Linux 系统上 🐧
-
打开终端 (Terminal)。
-
第一步:找出“租客”的身份证号 (PID)
使用lsof(list open files) 命令,查找谁在使用8087端口:lsof -i :8087你会看到类似这样的输出:
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME java 44455 dgq 50u IPv6 0x1234567890abcdef 0t0 TCP *:8087 (LISTEN)这里的 PID (Process ID, 进程ID)
44455就是我们要找的目标。 -
第二步:请“租客”离开
使用kill命令,根据 PID 强制终止这个进程:kill -9 44455-9参数代表一个“无法拒绝”的强制终止信号,能确保进程被彻底清理。
在 Windows 系统上 🪟
-
打开命令提示符 (CMD) 或 PowerShell (建议以管理员身份运行)。
-
第一步:找出“租客”的身份证号 (PID)
使用netstat命令:netstat -ano | findstr :8087你会看到类似这样的输出:
TCP 0.0.0.0:8087 0.0.0.0:0 LISTENING 12345最后一列的数字
12345就是 PID。 -
第二步:请“租客”离开
使用taskkill命令:taskkill /PID 12345 /F/F参数表示强制终止。
预防胜于治疗:如何避免问题?
- 使用 IDE 的重启功能: 相比于“停止”再“启动”,直接使用 IDE 的“重启 (Restart)”或“Rerun”功能,通常能更好地管理进程的生命周期。
- 优雅停机 (Graceful Shutdown): 确保你的应用配置了 Spring Boot Actuator 的
/shutdown端点,并在application.properties中启用它,这能让应用更可靠地关闭。 - 修改端口: 如果你确实需要同时运行多个服务,最简单的办法就是为它们配置不同的端口号,例如在
application.properties中设置server.port=8088。
结语
Address already in use 是每个后端开发者成长路上的“必修课”。虽然初见时可能会让人手足无措,但一旦你理解了其背后的“端口独占”原理,并掌握了 lsof/netstat 和 kill/taskkill 这套“侦查-行动”组合拳,这个问题就会从一个恼人的“拦路虎”,变成一个你只需30秒就能轻松解决的“小插曲”。
下次再遇到它,请不要慌张。深呼吸,打开终端,开始你的“端口猎杀”之旅吧!
✨ 总结与图表回顾 📊
📝 问题与解决方案总结表
| 遇到的问题 ❓ | 根本原因 🧐 | 关键命令 (macOS/Linux) 🐧 | 关键命令 (Windows) 🪟 |
|---|---|---|---|
APPLICATION FAILED TO START | 端口被占用 | lsof -i :<端口号> | netstat -ano | findstr :<端口号> |
BindException: Address already in use | 旧的应用进程未完全退出 | kill -9 <PID> | taskkill /PID <PID> /F |
🗺️ 调试流程图 (Flowchart)
🔄 交互时序图 (Sequence Diagram)
🚦 端口状态图 (State Diagram)
🏗️ 系统组件类图 (Class Diagram)
🔗 实体关系图 (Entity Relationship Diagram)
🧠 思维导图 (Markdown Format)

155

被折叠的 条评论
为什么被折叠?



