J'ai un crochet d'arrêt dans mon application (créé à l'aide de Runtime.getRuntime().addShutdownHook
). Cependant, si je lance l'application depuis Eclipse, le hook d'arrêt ne s'exécute pas lorsqu'il est arrêté.
Je pense que cela est dû au fait qu’Eclipse envoie au processus l’équivalent d’un signal d’abattage forcé, qui ne provoque pas l’exécution du crochet d’arrêt (équivalent de taskkill/F sous Windows ou de kill -p sous Linux), bien que Je ne suis pas absolument sûr.
Est-ce que quelqu'un sait comment contourner cela? J'utilise Windows (Vista) et j'ai le sentiment que cela pourrait être un problème spécifique à Windows, mais je ne suis pas sûr.
J'ai utilisé le hack suivant à la fin de ma méthode principale pour résoudre le problème:
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);
}
Tout d’abord, votre demande se termine-t-elle ou la mettez-vous de force? Si vous le forcez à le terminer (via le bouton d'arrêt), ce rapport de bogue Eclipse explique en détail pourquoi cela pourrait ne pas fonctionner.
Si vous ne le faites pas, vous avez peut-être raison de dire qu'il s'agit d'un comportement spécifique à Windows. Je suis sur un Mac, donc je ne peux pas confirmer, désolé. Cependant, je peux vous dire que le programme de test suivant fait exécute les crochets d'arrêt comme prévu.
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." );
}
}
Les Javadocs pour Runtime # addShutdownHook mentionnent que les crochets d'arrêt ne s'exécutent pas lorsque la JVM est abandonnée, ni abandonnée normalement, donc encore une fois, vos hypothèses sont correctes. Cela étant dit, voici quelques choses à essayer. Encore une fois, désolé, je ne peux pas confirmer ces informations à l’avance - pas de Windows ici. (Heureusement!)
Voici un script que vous pouvez exécuter en dehors d’Eclipse pour répertorier les processus disponibles exécutés sous Eclipse que vous pourriez tuer.
#!/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'"
Sous Windows, arrêtez gracieusement une application Java de manière standard, vous devez envoyer Ctrl + C à cela. Cela ne fonctionne qu'avec les applications de la console, mais Eclipse utilise javaw.exe
au lieu de Java.exe
. Pour résoudre ce problème, ouvrez la configuration de lancement, l'onglet JRE et sélectionnez "Alternative JRE:". La zone de groupe "Exécutable Java" apparaît et permet de saisir le fichier exécutable "Java".
Nous avons maintenant besoin d'un programme externe pour envoyer Ctrl-C à un processus avec une console cachée. J'ai trouvé des indices ici et ici . Notre programme se connecte à la console du processus souhaité et envoie l'événement à la console.
#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;
}
Test du programme 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);
}
}
Terminant le:
C:\>killsoft.exe 10520
Sortie du programme de test dans Eclipse:
pid: 10520
Sleeping...
Shutting down...
Je ne sais pas comment résoudre ce problème, mais IntelliJ a ajouté un bouton distinct à sa boîte de dialogue "Exécuter", qui arrête le VM de manière à appeler les crochets d'arrêt. Leur débogueur n'a pas cette fonctionnalité.
Sairam est ici, en appelant System.exit (0) , nous pouvons mettre fin à la machine virtuelle Eclipse et voir les résultats du hook
Je suis coincé dans Websphere pour le moment et je ne vois pas ce que je cherche . Mais je me souviens d'avoir une option de configuration d'exécution liée au lancement de l'application dans la même machine virtuelle . est-il possible de lancer votre application Java dans le même VM que le VM Eclipse?
Mais l'option me fait perdre la tête.