it-swarm.com.de

Wie bekomme ich den Shutdown-Hook für einen Prozess, der von Eclipse gestartet wird

Ich habe einen Shutdown-Hook in meiner Anwendung (erstellt mit Runtime.getRuntime().addShutdownHook). Wenn ich jedoch die Anwendung in Eclipse starte, wird der Shutdown-Hook beim Herunterfahren nicht ausgeführt. 

Ich denke, das liegt daran, dass Eclipse das Äquivalent eines Force-Kill-Signals an den Prozess sendet, wodurch der Shutdown-Hook nicht ausgeführt wird (entspricht Taskkill/F unter Windows oder kill -p unter Linux), obwohl ich Ich bin nicht absolut sicher.

Weiß jemand, wie man das umgehen kann? Ich verwende Windows (Vista) und habe das Gefühl, dass es sich um ein Windows-spezifisches Problem handelt, aber ich bin mir nicht sicher.

53
Neil

Ich habe den folgenden Hack am Ende meiner Hauptmethode verwendet, um das Problem zu umgehen:

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);
}  
23
Sairam R

Beendet Ihre Bewerbung oder beenden Sie sie mit Gewalt? Wenn Sie es gewaltsam beenden (über die Stopp-Schaltfläche), enthält dieses Eclipse-Fehlerbericht Details darüber, warum dies möglicherweise nicht funktioniert.

Andernfalls sind Sie möglicherweise in Bezug auf dieses Windows-spezifische Verhalten korrekt. Ich bin auf einem Mac und kann es nicht bestätigen. Ich kann Ihnen jedoch sagen, dass das folgende Testprogramm does die Shutdown-Hooks erwartungsgemäß ausführt.

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." );
    }
}

Die Javadocs für Runtime # addShutdownHook erwähnen, dass Shutdown-Hooks nicht ausgeführt werden, wenn die JVM abgebrochen wird, und nicht normal beendet werden. Wiederum sind Sie wahrscheinlich in Ihren Annahmen korrekt. Davon abgesehen, hier sind einige Dinge zu versuchen. Leider kann ich dies nicht rechtzeitig bestätigen - kein Windows hier. (Selig!)

  • Stellen Sie sicher, dass die JVM die Option - Xrs nicht enthält. Dies hat einen Nebeneffekt beim Herunterfahren von Hooks.
  • Starten Sie die JVM mit der Option - Server oder - Client . Ich habe die Erfahrung gemacht, dass das Edge-Case-Verhalten durch Auswahl des VM -Modus beeinflusst werden kann. (Vor allem im Hinblick auf Threading - zumindest auf dem Mac.)
  • Starten Sie Ihre App unter einem Profiler oder ähnlichem? Laden Sie native Bibliotheken?
  • Erhalten Sie einen schwerwiegenden Fehler und vermissen ihn? Zum Beispiel OutOfMemoryError oder dergleichen?
  • Aktivieren/deaktivieren Sie die Option Im Hintergrund starten im Dialogfeld Konfiguration ausführen Ihrer Anwendung in Eclipse.
  • Last but not least: Rufen Sie System.exit () manuell auf, wenn Sie die Möglichkeit dazu haben. :)
12
JLR

Hier ist ein Skript, das Sie außerhalb von Eclipse ausführen können, um die verfügbaren Prozesse aufzulisten, die unter Eclipse ausgeführt werden und die Sie beenden könnten.

#!/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'"
5
Jason Axelson

Unter Windows können Sie eine Java-Anwendung auf die übliche Art und Weise, die Sie senden müssen, ordnungsgemäß stoppen Ctrl + C dazu. Dies funktioniert nur mit Konsolen-Apps, Eclipse verwendet jedoch javaw.exe anstelle von Java.exe. Um dies zu lösen, öffnen Sie die Startkonfiguration, Registerkarte JRE und wählen Sie "Alternative JRE:". Das Gruppenfeld "Java ausführbar" wird angezeigt und ermöglicht die Eingabe der alternativen ausführbaren Datei "Java".

Jetzt benötigen wir ein externes Programm, um Strg-C an einen Prozess mit versteckter Konsole zu senden. Ich habe Hinweise gefunden hier und hier . Unser Programm hängt sich an die Konsole des gewünschten Prozesses an und sendet das Konsolenereignis.

#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-Programm testen:

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);
    }

}

Beende es:

C:\>killsoft.exe 10520

Testen Sie die Programmausgabe in Eclipse:

pid: 10520
Sleeping...
Shutting down...
1
basin

Ich bin nicht sicher, wie das Problem behoben werden kann, aber IntelliJ fügte seinem 'Ausführen'-Dialog eine separate Schaltfläche hinzu, mit der die VM auf eine Weise heruntergefahren werden, die die Shutdown Hooks aufruft. Ihr Debugger verfügt nicht über diese Funktion.

1
Javamann

Sairam ist hier richtig. Durch Aufruf von System.exit (0) können wir die Eclipse-JVM beenden und die Shutdown-Hook-Ergebnisse sehen

0
Shashank

Ich stecke im Moment in websphere fest und sehe nicht, wonach ich suche ... Aber ich erinnere mich, dass Eclipse eine Konfigurationsoption für das Starten der Anwendung in derselben VM hatte Möglicherweise starten Sie Ihre Java-Anwendung in derselben VM wie die Eclipse-VM?

Aber die Option entgeht mir.

0
guyumu