You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让Java程序退出后仍保持Windows服务运行,并在后续通过Java程序停止该服务?

如何让Java程序退出后仍保持Windows服务运行,并在后续通过Java程序停止该服务?

问题核心原因

你的启动命令存在关键错误:你用自己的test.exe(Socket服务器)来执行sc start命令,但test.exe并不是Windows的命令行工具cmd.exe,这导致你实际上是直接运行了test.exe作为Java的子进程,而非通过Windows服务控制管理器(SCM)启动服务。这种情况下,test.exe和Java进程存在父子关联,Java退出后它也会跟着停止。

解决方案步骤

1. 修正启动/停止命令,使用系统自带的sc.exe

Windows自带的sc.exe是专门用于管理服务的工具,通过它向SCM发送启动/停止指令,SCM会独立管理服务进程,和Java进程完全解耦,Java退出后服务会继续运行。

2. 正确处理外部命令的IO流

Java执行外部命令时,如果不处理子进程的输入/错误流,缓冲区满会导致子进程阻塞,进而影响命令的正常执行。

具体代码实现

启动服务的正确代码

// 调用Windows系统服务控制工具sc.exe启动服务
String[] startScript = {
    "C:\\Windows\\System32\\sc.exe",
    "start",
    "Test" // 你的服务名称
};

Process process = Runtime.getRuntime().exec(startScript);

// 处理子进程的标准输出(避免缓冲区阻塞)
new Thread(() -> {
    try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
        String line;
        while ((line = reader.readLine()) != null) {
            // 可选:记录启动日志
            // System.out.println("服务启动日志:" + line);
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}).start();

// 处理子进程的错误输出
new Thread(() -> {
    try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getErrorStream()))) {
        String line;
        while ((line = reader.readLine()) != null) {
            System.err.println("服务启动错误:" + line);
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}).start();

// 等待命令执行完成,检查退出码
int exitCode = process.waitFor();
if (exitCode == 0) {
    System.out.println("服务启动指令已成功提交给SCM");
} else {
    System.err.println("服务启动指令提交失败,退出码:" + exitCode);
}

停止服务的正确代码

// 调用sc.exe停止服务
String[] stopScript = {
    "C:\\Windows\\System32\\sc.exe",
    "stop",
    "Test" // 你的服务名称
};

Process stopProcess = Runtime.getRuntime().exec(stopScript);

// 同样处理IO流,避免阻塞
new Thread(() -> {
    try (BufferedReader reader = new BufferedReader(new InputStreamReader(stopProcess.getInputStream()))) {
        String line;
        while ((line = reader.readLine()) != null) {
            // 可选:记录停止日志
            // System.out.println("服务停止日志:" + line);
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}).start();

new Thread(() -> {
    try (BufferedReader reader = new BufferedReader(new InputStreamReader(stopProcess.getErrorStream()))) {
        String line;
        while ((line = reader.readLine()) != null) {
            System.err.println("服务停止错误:" + line);
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}).start();

int stopExitCode = stopProcess.waitFor();
if (stopExitCode == 0) {
    System.out.println("服务停止指令已成功提交给SCM");
} else {
    System.err.println("服务停止指令提交失败,退出码:" + stopExitCode);
}

额外验证步骤

确保你的服务本身能独立运行:

  1. 以管理员身份打开命令提示符,执行sc start Test
  2. 关闭命令提示符,打开服务管理器(services.msc)或任务管理器,检查Test服务是否持续运行
  3. 如果手动启动后服务也会停止,说明你的test.exe可能没有正确实现Windows服务的接口:
    • 如果你用工具(如NSSM、WinSW)包装控制台程序为服务,请检查工具的配置是否正确
    • 如果是自行开发的服务程序,请确保它正确处理SCM的服务控制请求(如调用RegisterServiceCtrlHandler等API)

备注:内容来源于stack exchange,提问作者defa0009

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.15 09:59:32