Fügen Sie einfach Informationen hinzu, die in anderen Antworten nicht vorhanden sind.
Wenn procfs /proc/self/cmdline
verfügbar ist
Wenn Sie in einer Umgebung ausgeführt werden, die procfs bereitstellt und daher über das /proc
Dateisystem verfügt (was bedeutet, dass dies keine tragbare Lösung ist), können Sie Java lesen lassen /proc/self/cmdline
, um sich selbst neu zu starten.
public static void restart() throws IOException {
new ProcessBuilder(getMyOwnCmdLine()).inheritIO().start();
}
public static String[] getMyOwnCmdLine() throws IOException {
return readFirstLine("/proc/self/cmdline").split("\u0000");
}
public static String readFirstLine(final String filename) throws IOException {
try (final BufferedReader in = new BufferedReader(new FileReader(filename))) {
return in.readLine();
}
}
Auf /proc/self/cmdline
verfügbaren Systemen ist dies wahrscheinlich die eleganteste Methode, um den aktuellen Java-Prozess von Java aus neu zu starten. Kein JNI beteiligt und kein Erraten von Pfaden und Sachen erforderlich. Dadurch werden auch alle an die java
Binärdatei übergebenen JVM-Optionen berücksichtigt . Die Befehlszeile ist genau identisch mit der des aktuellen JVM-Prozesses.
Viele UNIX-Systeme, einschließlich GNU / Linux (einschließlich Android), haben heutzutage procfs. Bei einigen wie FreeBSD ist es jedoch veraltet und wird auslaufen. Mac OS X ist eine Ausnahme in dem Sinne, dass es keine Prozesse gibt . Windows hat auch keine procfs . Cygwin hat Prozesse jedoch für Java nicht sichtbar, da es nur für Anwendungen sichtbar ist, die Cygwin-DLLs anstelle von Windows-Systemaufrufen verwenden, und Java Cygwin nicht kennt.
Vergiss nicht zu benutzen ProcessBuilder.inheritIO()
Die Standardeinstellung ist, dass stdin
/ stdout
/ stderr
(in Java mit dem Namen System.in
/ System.out
/ System.err
) des gestarteten Prozesses auf Pipes gesetzt sind, die es dem aktuell ausgeführten Prozess ermöglichen, mit dem neu gestarteten Prozess zu kommunizieren. Wenn Sie den aktuellen Prozess neu starten möchten, ist dies höchstwahrscheinlich nicht das, was Sie möchten . Stattdessen möchten Sie, dass stdin
// stdout
/ stderr
dieselben wie die der aktuellen VM sind. Dies wird als geerbt bezeichnet . Sie können dies tun, indem Sie inheritIO()
Ihren Anruf tätigenProcessBuilder
Instanz .
Fallstricke unter Windows
Ein häufiger Anwendungsfall einer restart()
Funktion ist das Neustarten der Anwendung nach einem Update. Das letzte Mal, als ich dies unter Windows versuchte, war dies problematisch. Beim Überschreiben der Anwendungsdatei .jar
mit der neuen Version begann sich die Anwendung schlecht zu verhalten und gab Ausnahmen über die .jar
Datei aus. Ich sage nur, falls dies Ihr Anwendungsfall ist. Damals löste ich das Problem, indem ich die Anwendung in eine Batch-Datei einwickelte und einen magischen Rückgabewert verwendete System.exit()
, den ich in der Batch-Datei abgefragt hatte, und stattdessen die Batch-Datei die Anwendung neu starten ließ.