首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計疑難解答

JVM 啟動流程與 .bat 腳本關係:關閉 CMD 視窗不影響 Java 程式運行

     編輯:程式設計疑難解答

現象:.bat 設定環境變數後啟動 java -jar app.jar,會出現三個程序:cmd.exe、java.exe (JVM)、conhost.exe。在工作管理員結束 cmd.exe 和 conhost.exe 後,JVM 仍在背景運行,使用者以為程式關閉而重複啟動,造成衝突。

根本原因

  • cmd.exe 是批次檔解譯器,負責啟動 JVM 進程。
  • JVM (java.exe) 一旦啟動,即成為獨立進程,**不再依賴父進程 cmd.exe 存活** (Windows 非 Unix fork 模式)。
  • conhost.exe 是主控台視窗宿主,僅負責輸入輸出轉發。

解決方案:防止重複啟動

方法 1:單一實例鎖 (推薦)

在 Java 程式啟動時建立檔案鎖或 Socket 埠鎖:

public class SingleInstance {
    private static FileLock lock;
    public static boolean tryLock(String lockFile) {
        try {
            RandomAccessFile raf = new RandomAccessFile(lockFile, "rw");
            lock = raf.getChannel().tryLock();
            return lock != null;
        } catch (IOException e) { return false; }
    }
    public static void main(String[] args) {
        if (!tryLock(System.getProperty("java.io.tmpdir") + "/myapp.lock")) {
            System.err.println("程式已在運行");
            System.exit(1);
        }
        // 正常啟動邏輯
    }
}

方法 2:.bat 改用 start /b 或 wscript 隱藏主控台

@echo off
set JAVA_HOME=...
start /b javaw -jar app.jar   // javaw 無主控台視窗
// 或
wscript //b //nologo //e:jscript // "%~f0"  // 更徹底隱藏

方法 3:啟動腳本檢查進程

@echo off
tasklist | findstr /i "java.exe" | findstr "app.jar" >nul
if %errorlevel% equ 0 (
    echo 已在運行
    timeout /t 3
    exit /b
)
start /b javaw -jar app.jar

最佳實踐建議

  1. 生產環境**直接用 javaw 或服務包裝器 (Procrun、NSSM、systemd)**,不要依賴 .bat + cmd 視窗。
  2. 程式碼層面實作單一實例鎖,雙重保險。
  3. 若必須用 .bat 除錯,加上 pause 讓使用者看到錯誤訊息,避免誤以為閃退而重啟。

理解「批次檔只是啟動器,JVM 是獨立進程」,再配合單一實例機制,即可徹底解決「關視窗程式還在跑、使用者重啟衝突」的問題。

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