Mac系统解决springboot项目启动报错:端口被占用

本文描述了一个项目部署后端口被占用的问题,解决方法是通过Mac终端使用lsof找到占用9090端口的进程,使用kill-9命令杀死进程,然后重新启动SpringBoot项目。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

项目场景:

1、部署都没有问题,但是运行后如图下图。这个图告诉我们,已经启动一个9090端口服务了。

2、进入端口显示如下图。这个图告诉我们,那个服务器正在正常运行。

所以我们要解决端口被占用的问题。


解决思路:

把占有端口的进程号杀死。

解决步骤:

1、进入Mac终端命令窗口,输入: lsof -i : 端口号 ,如下图,我的端口号是9090。

2、输入: kill -9 进程号,杀死进程号,如图。

这样子显示就是成功了,有一些端口可能被多个进程占用则需要多运行几次。

3、重新运行springboot项目。

<think>我们遇到了一个特殊问题:无论配置哪个端口号,Spring Boot 都报告端口占用。这通常不是简单的端口冲突,而是更深层次的问题。以下是系统化的解决方案: ### 一、排查非常规端口占用原因 1. **检查配置加载顺序** Spring Boot端口配置可能被多个来源覆盖,优先级为: ```mermaid graph LR A[命令行参数] -->|最高| B[系统属性] B --> C[环境变量] C --> D[application.properties/yml] ``` - 检查所有配置源: ```bash # 查看环境变量 echo $SERVER_PORT # Linux/Mac echo %SERVER_PORT% # Windows # 启动时添加调试参数 java -jar app.jar --debug ``` 2. **验证端口绑定机制** Spring Boot 2.4+ 使用双 Web 服务器架构时可能同时绑定多个端口[^4]: ```java // 检查是否同时启用了servlet和reactive @SpringBootApplication public class App { public static void main(String[] args) { SpringApplication.run(App.class, args); // 默认可能同时激活Tomcat和Netty } } ``` 解决方案:排除不必要的 Web 服务器 ```java @SpringBootApplication(exclude = {ReactiveWebServerFactoryAutoConfiguration.class}) ``` ### 二、解决进程残留问题 当 Spring Boot 应用异常退出时,可能因 JVM 僵尸进程导致端口未释放: 1. **跨平台查找 Java 僵尸进程** ```bash # Linux/Mac ps aux | grep java | grep -v grep # Windows tasklist /FI "IMAGENAME eq java.exe" ``` 2. **强制终止所有相关进程** ```bash # Linux/Mac kill -9 $(pgrep -f 'app.jar') # Windows taskkill /F /IM java.exe /FI "WINDOWTITLE eq app.jar" ``` ### 三、处理操作系统端口锁定 某些系统会临时保留关闭的端口(TCP TIME_WAIT 状态): 1. **检查端口保留状态** ```bash # Linux ss -tulpn | grep :9378 # Windows netstat -ano | findstr :9378 ``` 2. **缩短 TIME_WAIT 超时(Linux)** ```bash sudo sysctl -w net.ipv4.tcp_fin_timeout=15 # 默认60秒->15秒 ``` ### 四、规避 Spring Boot 内部机制冲突 当管理端口(management.server.port)与应用端口相同时会导致冲突[^4]: ```properties # 错误配置 server.port=8080 management.server.port=8080 # 冲突! ``` 修正方案: ```properties management.server.port=8081 ``` ### 五、终极解决方案:动态端口分配 在测试环境中强制使用随机端口: ```java @SpringBootApplication public class App implements WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> { public static void main(String[] args) { SpringApplication.run(App.class, args); } @Override public void customize(ConfigurableServletWebServerFactory factory) { factory.setPort(0); // 随机端口 } } ``` 启动日志将显示实际端口:`Tomcat started on port(s): 12345 (http)` ### 六、网络栈诊断 当怀疑操作系统网络栈故障时: 1. **重置 Windows 网络栈** ```cmd netsh int ip reset netsh winsock reset ``` 2. **Linux 释放所有 TCP 套接字** ```bash sudo sysctl -w net.ipv4.tcp_tw_reuse=1 ``` ### 验证流程 ```mermaid sequenceDiagram participant U as 用户 participant S as Spring Boot participant OS as 操作系统 U->>S: 启动应用 S->>OS: 请求绑定端口P alt 端口可用 OS-->>S: 绑定成功 S-->>U: 启动成功 else 端口被占 OS-->>S: 绑定失败 S-->>U: 报错 U->>OS: 执行诊断流程 OS-->>U: 返回诊断结果 U->>S: 调整配置后重启 end ``` > **数学约束**:端口分配本质是集合映射问题。设可用端口集合为: > $$ A = \{ p \in \mathbb{N} \mid 1024 \leq p \leq 65535 \} \setminus B $$ > 其中 $B$ 为已被占用端口集合。当 $|A| = 0$ 时系统无可用端口,但实际 $|A| = 64511$ 几乎不可能发生[^1]。 --- ### 相关问题 1. 如何设计 Spring Boot 应用的多端口监听机制? 2. 当 Kubernetes 中多个 Pod 需要相同服务端口时如何避免冲突? 3. TCP 协议中端口复用的实现原理是什么? 4. 如何监控 Spring Boot 应用的实时端口绑定状态? 5. 哪些 Linux 内核参数影响端口释放速度? [^1]: TCP 端口范围 $1024 \leq p \leq 65535$ 为用户可用范围 [^4]: 管理端口冲突问题</think>### Spring Boot 应用端口占用问题深度解决方案 无论配置哪个端口都显示被占用,这通常是由 Spring Boot 的生命周期管理机制或配置覆盖问题引起的。以下是系统化的解决方案: --- ### 一、根本原因分析 1. **应用未完全关闭** Spring Boot 注册了 JVM 关闭钩子(shutdown hook),但异常退出时可能未触发[^1],导致旧进程残留: $$ \text{残留进程} = \exists P_{\text{old}} \in \text{JVM Processes}, \quad \text{port}(P_{\text{old}}) = \text{配置端口} $$ 2. **配置覆盖问题** 多配置源优先级冲突: ```mermaid graph LR A[命令行参数] -->|最高| B[系统属性] B --> C[环境变量] C --> D[application.properties] ``` 环境变量可能覆盖你的配置 3. **管理端口冲突** 当启用 Actuator 时,管理端口可能绑定到相同端口[^4]: ```properties management.server.port=8081 # 必须显式设置不同端口 ``` --- ### 二、彻底解决方案 #### 步骤 1:强制终止所有残留进程 ```bash # Linux/Mac kill -9 $(pgrep -f 'jar your-app-name.jar') # Windows taskkill /F /IM java.exe ``` #### 步骤 2:验证端口释放 ```bash # 所有系统通用 lsof -i :你的端口号 || netstat -ano | findstr :你的端口号 ``` #### 步骤 3:解决配置覆盖问题 在 `application.properties` 中添加**最高优先级配置**: ```properties # 显式禁用所有覆盖源 spring.main.allow-bean-definition-overriding=false server.port=9379 # 明确指定端口 ``` #### 步骤 4:处理管理端口冲突 ```properties # application.properties management.server.port=9380 # 必须与server.port不同 management.endpoints.web.base-path=/manage # 自定义管理路径 ``` #### 步骤 5:确保优雅关闭 实现 `DisposableBean` 确保资源释放: ```java @Component public class PortCleaner implements DisposableBean { @Override public void destroy() { System.out.println("释放网络端口..."); // 添加自定义清理逻辑 } } ``` #### 步骤 6:使用随机端口(开发环境) ```properties server.port=0 # 随机分配可用端口 ``` --- ### 三、预防措施 1. **生命周期监控** 添加应用事件监听器: ```java @Component public class PortMonitor implements ApplicationListener<WebServerInitializedEvent> { @Override public void onApplicationEvent(WebServerInitializedEvent event) { System.out.println("端口激活: " + event.getWebServer().getPort()); } } ``` 2. **端口冲突自动处理** 实现 `WebServerFactoryCustomizer`: ```java @Bean public WebServerFactoryCustomizer<TomcatServletWebServerFactory> portCustomizer() { return factory -> { int port = 9378; while (isPortInUse(port)) port++; // 自动递增端口 factory.setPort(port); }; } ``` 3. **环境隔离配置** 使用 profile 指定端口: ```properties # application-dev.properties server.port=9378 # application-prod.properties server.port=80 ``` --- ### 四、验证流程 ```mermaid sequenceDiagram participant User participant SpringBoot participant OS User->>SpringBoot: 启动应用 SpringBoot->>OS: 请求端口P alt 端口可用 OS-->>SpringBoot: 分配成功 SpringBoot-->>User: 启动日志显示端口P else 端口被占 SpringBoot->>SpringBoot: 自动递增端口 SpringBoot->>OS: 请求端口P+1 OS-->>SpringBoot: 分配成功 SpringBoot-->>User: 警告+新端口信息 end ``` > **数学约束**:端口分配本质是整数资源分配问题: > $$ \text{可用端口} = \{ p \in \mathbb{N} \mid 1024 \leq p \leq 65535 \} \setminus \text{UsedPorts} $$ > Spring Boot端口选择算法需满足 $p \notin \text{UsedPorts}$ --- ### 相关问题 1. 如何为 Spring Boot Actuator 设计独立的安全端口配置? 2. 在 Kubernetes 环境中如何实现零停机时间端口切换? 3. 如何通过 JMX 动态修改运行中的 Spring Boot 应用端口? 4. Spring Boot 的优雅关闭机制如何防止 TCP 连接重置? 5. 哪些 Linux 内核参数会影响套接字释放速度? [^1]: SpringApplication 注册 JVM 关闭钩子确保优雅关闭 [^4]: 管理端口需要自定义绑定地址
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值