【发布时间】:2014-03-22 01:18:49
【问题描述】:
如果一个在java中创建的进程创建了一个子进程,然后又返回了,JVM就会挂起,但是没有进程ID。
下面的示例应用程序(需要 Windows 和 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);
}
}
当应用程序运行时,它会创建三个进程: java --> cmd --> 记事本 cmd 立即返回,java 调用 System.exit(0),这会杀死 java 进程。 但是记事本仍然存在,并且当从 gradle(或 eclipse 中)运行时,JVM 会一直徘徊,直到该进程消失,而不是返回它的返回值。
所以子进程仍然活着,但父进程已被部分杀死,但现在永远搁浅了。
重现这个的 build.gradle 脚本
apply plugin: 'java'
apply plugin: 'application'
mainClassName = "SubProcessHang"
执行 'gradle run' 并获得以下输出:
C:\HangDemo>gradlew run
:compileJava
:processResources UP-TO-DATE
:classes
:run
Process exit value:: 0
Output file length:: 0
> Building 75% > :run
我知道这一定与 java 进程的创建方式有关,但我不知道该怎么做。
除了获取正在运行的 java 进程的 ID 并在关闭挂钩中杀死所有子进程之外,我还能做什么?
【问题讨论】:
-
这看起来与我的 gradle 无关。您是否尝试过从命令行运行您的课程?
-
是的。它可以从命令行按预期工作(无论如何,正如我所料)。它返回退出状态,记事本仍在运行。问题是 gradle 是运行这里建模的 java 进程的自动化工具,并且永远不会返回。
标签: java process jvm gradle subprocess