为什么重新启动的Java程序会失去键盘焦点?

时间:2015-10-23 17:40:31

标签: java batch-file processbuilder shutdown-hook

我尝试创建一个简化的故障安全Java应用程序,只要它被强行关闭(在Windows中,使用CTRL + C的CMD命令),它就会自动重启。

批处理代码如下所示:

@echo off
setlocal

start /wait java BatchWakeMeUpSomehow

if errorlevel 1 goto retry
echo Finished successfully
exit

:retry
echo retrying...
start /wait java BatchWakeMeUpSomehow

java代码就是这个:

public class WakeMeUpSomehow {
    static class Message extends Thread {

        public void run() {
            try {

                while(true)
                {
                    System.out.println("Hello World from run");

                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        try {
            Runtime.getRuntime().addShutdownHook(new Message());
            while(true)
            {
                System.out.println("Hello World");
                Thread.sleep(100);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

我想澄清一下我的理解。我认为因为Java在JVM环境中运行,所以它在重启被强行关闭的JVM方面有一些限制(如果我们通过批处理文件重新启动强制关闭的JVM,那么它会丢失光标焦点而它只是在一个无法使用键盘焦点的新CMD窗口中运行。

我的目标是让这个应用程序继续在循环中运行(la"数字wackamole"),但我只能重新运行一次(它在非运行中运行) - 响应CMD窗口)

有人曾建议我查看Apache Daemon工具,但我不确定这有多大帮助。

1 个答案:

答案 0 :(得分:1)

要在错误级别1及以上的情况下进行无限循环,请在start行之前添加标签:

:run
start /wait java BatchWakeMeUpSomehow
if errorlevel 1 echo retrying... & goto run
echo Finished successfully

但是这也会打开一个新窗口,因此如果要在已启动的窗口中重新启动java进程,可以使用typeperf检查其CPU使用情况(以便强行关闭)进程并重新启动它)或者只是在执行返回批处理文件后重新启动java

  • 如果java进程退出(不挂起),我们可以使用tasklist检测到它:

    :run
        start java BatchWakeMeUpSomehow
    :check
        timeout 1 >nul
        tasklist /fi "imagename eq java.exe" | find "java.exe" >nul
        if errorlevel 1 echo retrying... & goto run
        goto check
    
  • 如果java进程挂起并且CPU使用率为0%,持续1分钟:

    if not "%~1"=="childprocess" goto main
    :loop
        java BatchWakeMeUpSomehow
        goto loop
    
    :main
        start "" "%~dpnx0" childprocess
    :check
        for /f "skip=2 delims=, tokens=2" %%a in ('
            typeperf "\process(java)\%% processor time" -sc 1 -si 60
        ') do if %%a=="0.000000" taskkill /f /im java.exe
        goto check