it-swarm.com.de

Wie kann man Java anmutig verarbeiten?

Wie halte ich einen Java -Prozess unter Linux und Windows ordnungsgemäß an?

Wann wird Runtime.getRuntime().addShutdownHook aufgerufen und wann nicht?

Was ist mit Finalisierern, helfen sie hier?

Kann ich ein Signal von einer Shell an einen Java -Prozess senden?

Ich suche vorzugsweise tragbare Lösungen.

85
Ma99uS

Shutdown-Hooks werden in allen Fällen ausgeführt, in denen VM nicht gewaltsam getötet wird. Wenn Sie also einen "Standard" -Tötungsbefehl (SIGTERM von einem Tötungsbefehl) ausgeben, werden sie ausgeführt Ebenso werden sie ausgeführt, nachdem System.exit(int) aufgerufen wurde.

Jedoch ein harter Schlag (kill -9 oder kill -SIGKILL) dann werden sie nicht ausgeführt. Ebenso (und offensichtlich) werden sie nicht ausgeführt, wenn Sie den Strom vom Computer abziehen, ihn in einen Behälter mit kochender Lava legen oder die CPU mit einem Vorschlaghammer in Stücke schlagen. Das wusstest du aber wahrscheinlich schon.

Finalizer sollten eigentlich auch laufen, aber es ist am besten, sich bei der Bereinigung des Herunterfahrens nicht darauf zu verlassen, sondern sich auf Ihre Shutdown-Hooks zu verlassen, um die Dinge sauber zu stoppen. Und, wie immer, sei vorsichtig mit Deadlocks (ich habe gesehen, dass viel zu viele Shutdown Hooks den gesamten Prozess hängen)!

79
jsight

Ok, nach all den Möglichkeiten, die ich gewählt habe, um mit "Java Monitoring and Management" zu arbeiten
Übersicht ist hier
So können Sie relativ einfach eine Anwendung von einer anderen aus steuern. Sie können die steuernde Anwendung von einem Skript aus aufrufen, um die gesteuerte Anwendung ordnungsgemäß zu beenden, bevor Sie sie beenden.

Hier ist der vereinfachte Code:

Kontrollierte Anwendung:
Führen Sie es mit den folgenden VM Parametern aus:
- Dcom.Sun.management.jmxremote
- Dcom.Sun.management.jmxremote.port = 9999
- Dcom.Sun.management.jmxremote.authenticate = false
- Dcom.Sun.management.jmxremote.ssl = false

//ThreadMonitorMBean.Java
public interface ThreadMonitorMBean
{
String getName();
void start();
void stop();
boolean isRunning();
}

// ThreadMonitor.Java
public class ThreadMonitor implements ThreadMonitorMBean
{
private Thread m_thrd = null;

public ThreadMonitor(Thread thrd)
{
    m_thrd = thrd;
}

@Override
public String getName()
{
    return "JMX Controlled App";
}

@Override
public void start()
{
    // TODO: start application here
    System.out.println("remote start called");
}

@Override
public void stop()
{
    // TODO: stop application here
    System.out.println("remote stop called");

    m_thrd.interrupt();
}

public boolean isRunning()
{
    return Thread.currentThread().isAlive();
}

public static void main(String[] args)
{
    try
    {
        System.out.println("JMX started");

        ThreadMonitorMBean monitor = new ThreadMonitor(Thread.currentThread());

        MBeanServer server = ManagementFactory.getPlatformMBeanServer();

        ObjectName name = new ObjectName("com.example:type=ThreadMonitor");

        server.registerMBean(monitor, name);

        while(!Thread.interrupted())
        {
            // loop until interrupted
            System.out.println(".");
            try 
            {
                Thread.sleep(1000);
            } 
            catch(InterruptedException ex) 
            {
                Thread.currentThread().interrupt();
            }
        }
    }
    catch(Exception e)
    {
        e.printStackTrace();
    }
    finally
    {
        // TODO: some final clean up could be here also
        System.out.println("JMX stopped");
    }
}
}

Steueranwendung:
Führen Sie es mit stop oder start als Befehlszeilenargument aus

public class ThreadMonitorConsole
{

public static void main(String[] args)
{
    try
    {   
        // connecting to JMX
        System.out.println("Connect to JMX service.");
        JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://:9999/jmxrmi");
        JMXConnector jmxc = JMXConnectorFactory.connect(url, null);
        MBeanServerConnection mbsc = jmxc.getMBeanServerConnection();

        // Construct proxy for the the MBean object
        ObjectName mbeanName = new ObjectName("com.example:type=ThreadMonitor");
        ThreadMonitorMBean mbeanProxy = JMX.newMBeanProxy(mbsc, mbeanName, ThreadMonitorMBean.class, true);

        System.out.println("Connected to: "+mbeanProxy.getName()+", the app is "+(mbeanProxy.isRunning() ? "" : "not ")+"running");

        // parse command line arguments
        if(args[0].equalsIgnoreCase("start"))
        {
            System.out.println("Invoke \"start\" method");
            mbeanProxy.start();
        }
        else if(args[0].equalsIgnoreCase("stop"))
        {
            System.out.println("Invoke \"stop\" method");
            mbeanProxy.stop();
        }

        // clean up and exit
        jmxc.close();
        System.out.println("Done.");    
    }
    catch(Exception e)
    {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}
}


Das ist es. :-)

47
Ma99uS

Eine andere Möglichkeit: Ihre Anwendung kann einen Server-Socet öffnen und auf Informationen warten, die dort eingehen. Zum Beispiel eine Zeichenkette mit einem "magischen" Wort :) und dann reagieren, um das Herunterfahren durchzuführen: System.exit (). Sie können solche Informationen mit einer externen Anwendung wie Telnet an die Socke senden.

7
Ermak

Ähnliche Frage hier

Finalizer in Java sind schlecht. Sie erhöhen den Aufwand für die Garbage Collection erheblich. Vermeiden Sie sie, wann immer dies möglich ist.

Der shutdownHook wird nur aufgerufen, wenn der VM heruntergefahren wird. Ich denke, er kann sehr gut tun, was Sie wollen.

2
Steve g

Hier ist eine etwas knifflige, aber tragbare Lösung:

  • Implementieren Sie in Ihrer Anwendung einen Shutdown-Hook
  • Wenn Sie Ihre JVM ordnungsgemäß herunterfahren möchten, installieren Sie einen Java Agent , der System.exit () mit dem - aufruft. API anhängen .

Ich habe den Java Agent implementiert. Er ist auf Github verfügbar: https://github.com/everit-org/javaagent-shutdown

Eine detaillierte Beschreibung der Lösung finden Sie hier: https://everitorg.wordpress.com/2016/06/15/shutting-down-a-jvm-process/

2
Balazs Zsoldos

Danke für eure Antworten. Shutdown hakt Nähte wie etwas, das in meinem Fall funktionieren würde. Aber ich bin auch auf das gestoßen, was Monitoring and Management Beans heißt:
http://Java.Sun.com/j2se/1.5.0/docs/guide/management/overview.html
Dies bietet einige nette Möglichkeiten für die Fernüberwachung und Manipulation des Java) -Prozesses. (Wurde in Java 5) eingeführt.)

0
Ma99uS

Die Signalisierung unter Linux kann mit "kill" (man kill für die verfügbaren Signale) erfolgen. Dazu benötigen Sie die Prozess-ID. (ps ax | grep Java) oder so ähnlich, oder speichern Sie die Prozess-ID, wenn der Prozess erstellt wird (dies wird in den meisten Linux-Startdateien verwendet, siehe /etc/init.d)

Portable Signalisierung kann durch Integration eines SocketServers in Ihre Java) - Anwendung erfolgen. Dies ist nicht so schwierig und gibt Ihnen die Freiheit, jeden gewünschten Befehl zu senden.

Wenn Sie schließlich Klauseln anstelle von Finalisierern meinten; Sie werden nicht ausgeführt, wenn System.exit () aufgerufen wird. Finalizer sollten funktionieren, aber nichts Wichtigeres tun, als eine Debug-Anweisung auszudrucken. Sie sind gefährlich.

0
extraneon