Wenn ein in Java erstellter Prozess einen Unterprozess erstellt, aber dann zurückkehrt, hängt die JVM, jedoch ohne Prozess-ID.Warum hängt ein Java-Prozess von Gradle, wenn der Unterprozess noch offen ist?
Beispielanwendung unter (erfordert Windows und Java 7)
import java.io.File;
import java.io.IOException;
import java.lang.ProcessBuilder.Redirect;
import java.nio.file.Files;
public class SubProcessHang {
public static void main(String[] args) throws IOException, InterruptedException {
ProcessBuilder builder = new ProcessBuilder("cmd", "/c", "start", "notepad.exe");
File output = Files.createTempFile("output", "txt").toFile();
builder.redirectError(Redirect.to(output));
builder.redirectOutput(Redirect.to(output));
Process process = builder.start();
process.waitFor();
int exitValue = process.exitValue();
System.out.println("Process exit value:: " + exitValue);
System.out.println("Output file length:: " + output.length());
System.exit(exitValue);
}
}
Wenn die Anwendung ausgeführt wird, ist es drei Prozesse erzeugt: java -> cmd -> Notizblock cmd sofort zurück und Java Rufe System. exit (0), wodurch der Java-Prozess beendet wird. Aber Notepad ist immer noch da, und wenn es von Gradle (oder Eklipse für diese Angelegenheit) ausgeführt wird, hängt die JVM herum, bis dieser Prozess weggeht, und gibt seinen Rückgabewert nicht zurück.
So ist der Kinderprozess noch am Leben, aber der Elternprozess wurde teilweise getötet, ist aber für immer gestrandet.
Das build.gradle Skript dieses
apply plugin: 'java'
apply plugin: 'application'
mainClassName = "SubProcessHang"
Ausführen ‚gradle run‘ und erhalten diese Ausgabe zu reproduzieren:
C:\HangDemo>gradlew run
:compileJava
:processResources UP-TO-DATE
:classes
:run
Process exit value:: 0
Output file length:: 0
> Building 75% > :run
Ich weiß es etwas damit zu tun haben müssen, wie die Java-Prozesse erstellt, aber ich habe keine Ahnung was zu tun ist.
Was kann ich tun, um die ID des laufenden Java-Prozesses zu erhalten und alle Unterprozesse in einem Shutdown-Hook zu beenden?
Das sieht nicht so aus, als ob es wirklich etwas mit Gradle zu mir zu tun hat. Haben Sie versucht, Ihre Klasse einfach über eine Befehlszeile auszuführen? –
Ja. Es funktioniert wie erwartet (wie ich sowieso erwarten würde) von der Befehlszeile. Es gibt den Exit-Status zurück und der Editor wird noch ausgeführt. Das Problem ist, dass Gradle das Automatisierungswerkzeug ist, das den hier modellierten Java-Prozess ausführt und niemals zurückkehrt. – w25r