Как получить завершающий крючок для выполнения в процессе, запущенном с Eclipse
У меня есть приложение для завершения работы в моем приложении (созданное с помощью Runtime.getRuntime().addShutdownHook
). Однако, если я запустил приложение из Eclipse, когда он выключен, то завершение работы не выполняется.
Я думаю, это связано с тем, что Eclipse отправляет эквивалент сигнала принудительного уничтожения в процесс, что не приводит к запуску крюка отключения (эквивалент taskkill/F в Windows или kill -p в Linux), хотя я не уверен.
Кто-нибудь знает, как обойти это? Я запускаю Windows (Vista), и я чувствую, что это может быть проблема с Windows, но я не уверен.
Ответы
Ответ 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...