首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 程式設計入門

Java 編寫 Windows NT 服務實戰:基於 Microsoft SDK for Java 的完整指南

     編輯:Java 程式設計入門

NT 服務本質:長駐後台的系統級進程

Windows NT 服務(現稱 Windows Service)是無用戶界面、隨系統啟動、以特定賬號(如 LocalSystem)運行、由 SCM (Service Control Manager) 管理的長生命周期進程。類似 Unix/Linux 的 Daemon。典型例子:SQL Server、IIS、Print Spooler。

核心特徵

  • 自啟動/手動/禁用:通過 SCM 配置啟動類型。
  • 無 GUI:運行於 Session 0 隔離會話,不與用戶桌面交互(Vista+ 強制)。
  • SCM 管理:安裝、啟動、停止、暫停、繼續、卸載均通過 SCM API。
  • 特定身份運行:默認 LocalSystem(高權限),可配置域賬號/本地賬號實現最小權限原則。
  • 線程模型:服務進程內部通常啟動工作線程處理業務,主線程等待 SCM 控制碼。

Java 實現 NT 服務的挑戰與方案

標準 Java SE 無原生 API 操作 SCM。歷史方案:

  1. Microsoft SDK for Java (J/Direct, com.ms.service):微軟專有,僅運行於 MS JVM,**已停止維護,不推薦新項目使用**。
  2. JavaService / Procrun (Apache Commons Daemon):開源、跨平台、主流選擇,包裝 JVM 為原生服務可執行文件。
  3. WinRun4J / Yet Another Java Service Wrapper (YAJSW):輕量級 Wrapper,生成 .exe 啟動 JVM。
  4. Spring Boot + winsw:現代微服務常用,打包為可執行 JAR,winsw 生成服務 XML。

歷史回顧:Microsoft SDK for Java 實現流程(僅供理解遺留系統)

環境準備

  • 安裝 Microsoft SDK for Java 4.0(含 service.zip 類庫、jntsvc.exe 打包工具)。
  • 將 service.zip 解壓至 %JAVA_HOME%\jre\lib\ext(擴展類加載路徑)。
  • 將 jntsvc.exe 目錄加入 PATH。

編寫服務類

import com.ms.service.Service;
import com.ms.service.ServiceControl;

public class EchoSvc extends Service {
    private Thread workerThread;
    private volatile boolean running = false;

    @Override
    public void startService() {
        running = true;
        workerThread = new Thread(() -> {
            while (running) {
                // 業務邏輯:Socket 監聽、定時任務等
                try { Thread.sleep(5000); } catch (InterruptedException ignored) {}
            }
        });
        workerThread.start();
    }

    @Override
    public void stopService() {
        running = false;
        workerThread.interrupt();
        try { workerThread.join(5000); } catch (InterruptedException ignored) {}
    }

    public static void main(String[] args) {
        // 僅供測試,實際由 SCM 調用
        EchoSvc svc = new EchoSvc();
        svc.startService();
    }
}

編譯與打包

javac EchoSvc.java
jntsvc *.class /OUT:EchoSvc.exe /SVCMAIN:EchoSvc "/SERVICENAME:EchoSvc"
  • /OUT:生成可執行文件名。
  • /SVCMAIN:包含 startService/stopService 的入口類。
  • /SERVICENAME:註冊表服務名。

安裝與測試

EchoSvc.exe -install    // 註冊到 SCM
net start EchoSvc       // 啟動
net stop EchoSvc        // 停止
EchoSvc.exe -uninstall  // 卸載

現代最佳實踐:Apache Commons Daemon (Procrun)

強烈建議新項目使用此方案,支持 JDK 8/11/17/21,開源、活躍維護。

Maven 依賴

<dependency>
    <groupId>commons-daemon</groupId>
    <artifactId>commons-daemon</artifactId>
    <version>1.3.4</version>
</dependency>

實現 Daemon 接口

org.apache.commons.daemon.Daemon
public class MyService implements Daemon {
    private Thread worker;
    private volatile boolean running = false;

    @Override
    public void init(DaemonContext context) throws Exception {
        // 解析命令行參數、加載配置
    }

    @Override
    public void start() throws Exception {
        running = true;
        worker = new Thread(this::runLoop);
        worker.start();
    }

    @Override
    public void stop() throws Exception {
        running = false;
        worker.interrupt();
        worker.join(10000);
    }

    @Override
    public void destroy() {
        // 清理資源
    }

    private void runLoop() {
        while (running) { /* 業務邏輯 */ }
    }
}

prunsrv.exe 安裝命令

prunsrv.exe //IS//MyService \
  --DisplayName="My Java Service" \
  --Install="C:\path\prunsrv.exe" \
  --Jvm=auto \
  --Classpath="C:\app\lib\*;C:\app\my-service.jar" \
  --StartMode=jvm --StartClass=com.app.MyService --StartMethod=start \
  --StopMode=jvm --StopClass=com.app.MyService --StopMethod=stop \
  --LogPath="C:\app\logs" --StdOutput=auto --StdError=auto \
  --User=DOMAIN\svc_account --Password=***

關鍵最佳實踐

  1. 日誌輸出重定向:服務無控制台,務必配置文件日誌(Logback/Log4j2 + RollingFileAppender)。
  2. 優雅關閉:實現 stop()/destroy() 釋放端口、關閉連接池、刷新緩存。
  3. 健康檢查端點:內嵌 HTTP 端點(如 :8080/health)供監控系統探活。
  4. 最小權限原則:創建專用服務賬號,僅授予必要目錄/註冊表/網絡權限。
  5. JVM 參數調優:-Xms -Xmx -XX:+UseG1GC -XX:MaxMetaspaceSize 等通過 --JvmOptions 傳遞。
  6. 避免 Session 0 隔離問題:不彈窗、不訪問用戶桌面、文件路徑用絕對路徑。

總結

Java 編寫 Windows 服務的核心是將 JVM 進程包裝為 SCM 可識別的原生進程。歷史上 Microsoft SDK 提供了原生類庫但已淘汰;現代標準方案是 Apache Commons Daemon (Procrun) 或 winsw,配合 Daemon 接口實現生命周期管理。掌握服務安裝、日誌、優雅關閉、權限控制等工程化細節,才能構建生產級穩定的 Windows 後台服務。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved