Почему моя перезапущенная Java-программа теряет фокус клавиатуры?

Я попытался создать упрощенное отказоустойчивое Java-приложение, которое будет перезапускать себя всякий раз, когда оно было принудительно завершено (в Windows, используя команду CMD CTRL+C).

Пакетный код выглядит так:

@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, которое не может иметь фокус клавиатуры.

Моя цель состояла в том, чтобы это приложение продолжало работать в цикле ("цифровой wackamole"), но я могу когда-либо перезапустить его только один раз (когда оно работает в неотвечающем окне CMD)

Кто-то предложил мне посмотреть на инструмент Apache Daemon, но я не уверен, как это поможет.

1 ответ

Решение

Чтобы сделать бесконечный цикл в случае уровня ошибки 1 и выше, добавьте метку перед start линия:

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

Однако это также откроет новое окно, поэтому, если вы хотите перезапустить java процесс в уже запущенном окне вы можете использовать typeperf проверить использование процессора (чтобы можно было принудительно закрыть процесс и перезапустить его) или просто запустить 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 процесс зависает и загрузка процессора составляет 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
    
Другие вопросы по тегам