如何优雅停止作为Windows服务运行的Quarkus应用避免崩溃误判
解决Quarkus作为Windows服务时优雅停止的问题
核心问题:调用Quarkus.asyncExit()会触发System.exit(),导致Windows服务被判定为崩溃,需要让应用在停止时返回控制权给启动线程而非直接退出JVM。
可行方案
1. 使用编程式QuarkusApplication控制生命周期
放弃直接调用Quarkus.run(),转而实现QuarkusApplication接口,手动控制应用的启动与停止流程,避免框架自动调用System.exit():
import io.quarkus.runtime.Quarkus; import io.quarkus.runtime.QuarkusApplication; import io.quarkus.runtime.annotations.QuarkusMain; @QuarkusMain public class WindowsServiceApp implements QuarkusApplication { private volatile boolean running = true; @Override public int run(String... args) throws Exception { // 启动Quarkus应用上下文 Quarkus.run(args); // 阻塞直到停止信号触发 while (running) { Thread.sleep(1000); } // 优雅关闭应用上下文 Quarkus.close(); return 0; // 返回而非调用System.exit() } // 供Windows服务停止时调用的方法 public void stop() { running = false; } }
这种方式下,Windows服务的stop方法只需调用WindowsServiceApp.stop(),让run方法自然结束并返回,不会触发System.exit(),Windows服务会被判定为正常停止。
2. 替换Quarkus默认的退出逻辑
通过自定义任务修改Quarkus的退出行为,避免调用System.exit():
- 创建自定义
ShutdownTask,注册到Quarkus生命周期中,在退出时完成资源清理后通知主线程结束:
import io.quarkus.runtime.ShutdownTask; import jakarta.enterprise.context.ApplicationScoped; @ApplicationScoped public class CustomShutdownTask implements ShutdownTask { private final Runnable onShutdown; public CustomShutdownTask(Runnable onShutdown) { this.onShutdown = onShutdown; } @Override public void shutdown() { // 执行自定义资源清理逻辑 // ... // 通知主线程结束阻塞 onShutdown.run(); } }
在启动类中注册任务并阻塞等待停止信号:
public class WindowsServiceRunner { private volatile boolean running = true; public void start() { Quarkus.run(args -> { CustomShutdownTask shutdownTask = new CustomShutdownTask(() -> running = false); Quarkus.registerShutdownTask(shutdownTask); return 0; }); // 阻塞直到收到停止信号 while (running) { Thread.sleep(1000); } } public void stop() { // 触发Quarkus优雅关闭流程 Quarkus.asyncExit(); } }
3. 避开System.exit()的配置调整
由于Java 17已废弃安全管理器,不推荐使用该方案。可尝试通过Quarkus配置调整退出行为:
- 设置
quarkus.shutdown.exit-code=-1(需验证版本兼容性),让Quarkus在退出时不调用System.exit(),但需配合自定义逻辑让主线程正确结束。
关键注意点
- 确保Windows服务的stop方法仅触发Quarkus优雅关闭流程,而非直接终止进程。
- 所有资源(数据库连接、线程池等)需在自定义ShutdownTask中完成清理,避免资源泄漏。
内容的提问来源于stack exchange,提问作者ewramner
相关产品推荐
相关产品推荐

