Подтвердить что ты не робот

Как получить завершающий крючок для выполнения в процессе, запущенном с Eclipse

У меня есть приложение для завершения работы в моем приложении (созданное с помощью Runtime.getRuntime().addShutdownHook). Однако, если я запустил приложение из Eclipse, когда он выключен, то завершение работы не выполняется.

Я думаю, это связано с тем, что Eclipse отправляет эквивалент сигнала принудительного уничтожения в процесс, что не приводит к запуску крюка отключения (эквивалент taskkill/F в Windows или kill -p в Linux), хотя я не уверен.

Кто-нибудь знает, как обойти это? Я запускаю Windows (Vista), и я чувствую, что это может быть проблема с Windows, но я не уверен.

4b9b3361

Ответ 1

Я использовал следующий хак в конце моего основного метода, чтобы обойти проблему:

if (Boolean.parseBoolean(System.getenv("RUNNING_IN_ECLIPSE"))) {
    System.out.println("You're using Eclipse; click in this console and " +
            "press ENTER to call System.exit() and run the shutdown routine.");
    try {
        System.in.read();
    } catch (IOException e) {
        e.printStackTrace();
    }
    System.exit(0);
}  

Ответ 2

Во-первых, ваше приложение заканчивается или вы принудительно завершаете его? Если вы принудительно завершаете его (через кнопку остановки), этот отчет об ошибке Eclipse содержит сведения о том, почему это может не работать.

В противном случае вы можете быть прав в отношении того, что это поведение, зависящее от Windows. Я нахожусь на Mac, поэтому не могу подтвердить, извините. Тем не менее, я могу сказать вам, что следующая тестовая программа выполняет ожидающие завершения выключения.

public class MyShutdownHook
{
    public static void main( String[] args )
    {
        System.out.println( "Entering main." );

        Runtime.getRuntime().addShutdownHook( 
            new Thread(
                new Runnable() {
                    public void run() {
                        System.out.println( "Shutdown hook ran." );
                    }   
                }
            )
        );

        System.out.println( "Exiting main." );
    }
}

Javadocs for Runtime # addShutdownHook упоминает, что выключения не запускаются, когда JVM прерывается, а не выходит из строя, вы, вероятно, правы в своих предположениях. Это, как говорится, вот некоторые вещи, чтобы попробовать. Снова, извините, я не могу подтвердить это раньше времени - здесь нет Windows. (Благословенно!)

  • Убедитесь, что JVM не включает параметр -Xrs. Это имеет побочный эффект на крючках остановки.
  • Попробуйте запустить JVM с помощью параметра -сервера или -клиент. По моему опыту, поведение в крайнем случае может быть вызвано выбором режима VM. (Особенно в отношении резьбы - по крайней мере, на Mac.)
  • Вы запускаете свое приложение под профилировщиком или тому подобное? Загрузка каких-либо родных библиотек?
  • Вы получаете какую-то фатальную ошибку и пропустили ее? Например, OutOfMemoryError или тому подобное?
  • Попробуйте проверить/снять флажок Запустить в фоновом режиме из приложения Запустить диалоговое окно конфигурации в Eclipse.
  • И последнее, но не менее важное: вызывать System.exit() вручную, если у вас есть такая возможность.:)

Ответ 3

Здесь script, который вы можете запустить за пределами eclipse, чтобы просмотреть доступные процессы, запущенные в Eclipse, которые вы могли бы убить.

#!/bin/bash
set -o nounset                              # Treat unset variables as an error

PROCESSES=$(ps axo pid,ppid,command)

# Find eclipse launcher PID
LAUNCHER_PID=$(echo "$PROCESSES" | grep "/usr/lib/eclipse/eclipse" |grep -v "launcher"|awk '{print $1}')
echo "Launcher PID $LAUNCHER_PID"

# Find eclipse PID
ECLIPSE_PID=$(echo "$PROCESSES" | egrep "[[:digit:]]* $LAUNCHER_PID " | awk '{print $1}')
echo "Eclipse PID $ECLIPSE_PID"

# Find running eclipse sub-process PIDs
SUB_PROCESS=$(echo "$PROCESSES" | egrep "[[:digit:]]* $ECLIPSE_PID " | awk '{print $1}')

# List processes
echo
for PROCESS in $SUB_PROCESS; do
    DRIVER=$(ps --no-headers o pid,ppid,command $PROCESS | awk '{print $NF}')
    echo "$PROCESS $DRIVER"
done

echo "Kill a process using: 'kill -SIGTERM \$PID'"

Ответ 4

Я не уверен, как это исправить, но IntelliJ добавила отдельную кнопку в свой диалог "Запуск", который отключит виртуальную машину таким образом, что вызовет "Крюки выключения". Их отладчик не имеет этой функции.

Ответ 5

В настоящий момент я застрял в websphere и не вижу, что я ищу. Но я помню, как eclipse имеет параметр конфигурации запуска, связанный с запуском приложения в той же виртуальной машине. Возможно ли запуск вашего приложения Java в той же виртуальной машине, что и виртуальная машина eclipse?

Но этот вариант подскакивает.

Ответ 6

Сайрам прямо здесь, вызывая System.exit(0), мы можем закончить JVM eclipse и увидеть результаты завершения работы Shutdown

Ответ 7

В Windows, чтобы изящно остановить Java-приложение стандартным образом, вам нужно отправить Ctrl + C. Это работает только с консольными приложениями, но Eclipse использует javaw.exe вместо java.exe. Чтобы решить эту проблему, откройте конфигурацию запуска, вкладку JRE и выберите "Alternative JRE:". Появится поле группы "Java executable" и позволяет ввести альтернативный исполняемый файл "java".

Теперь нам нужна внешняя программа для отправки Ctrl-C в процесс со скрытой консолью. Я нашел подсказки здесь и здесь. Наша программа присоединяется к консоли желаемого процесса и отправляет событие консоли.

#include <stdio.h>
#include <windows.h>

int main(int argc, char* argv[])
{
    if (argc == 2) {
        unsigned pid = 0;
        if (sscanf_s(argv[1], "%u", &pid) == 1) {
            FreeConsole(); // AttachConsole will fail if we don't detach from current console
            if (AttachConsole(pid)) {
                //Disable Ctrl-C handling for our program
                SetConsoleCtrlHandler(NULL, TRUE);
                GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0);
                return 0;
            }
        }
    }

    return 1;
}

Проверить java-программу:

public class Shuthook {

    public static void main(final String[] args) throws Exception {
        Runtime.getRuntime().addShutdownHook(new Thread() {
            @Override
            public void run() {
                System.out.println("Shutting down...");
            }
        });

        String sPid = ManagementFactory.getRuntimeMXBean().getName();
        sPid = sPid.substring(0, sPid.indexOf('@'));

        System.out.println("pid: " + sPid);
        System.out.println("Sleeping...");
        Thread.sleep(1000000);
    }

}

Завершение:

C:\>killsoft.exe 10520

Выход тестовой программы в Eclipse:

pid: 10520
Sleeping...
Shutting down...