如果未使用waitFor
,则终止JVM对其子进程没有影响。这是一个例子。
Bash脚本:
#!/usr/bin/env bash
echo "Sleeping..." > 'log'
sleep 30
echo "Wake up" >> 'log'
Java代码:
public class Code {
public static void main(String[] args) throws Exception {
Process process = Runtime.getRuntime().exec("./child.sh");
// process.waitFor();
}
}
发出Java Code
后,JVM立即终止。 ps -ef | grep 'child.sh' | grep -v grep
显示:
jing 3535 2761 0 13:47 pts/15 00:00:00 bash ./child.sh
然后在30秒后,我检查当前目录中log
文件的内容。内容是:
Sleeping...
Wake up
上面的grep
命令现在没有显示任何内容。现在我取消注释process.waitFor()
并重新编译Code.java
。运行java Code
后,我使用上面的grep
命令来验证child.sh
子进程是否正在运行。然后我发出Ctrl-C
,JVM终止。现在运行上面的grep
命令什么都没有显示。 log
文件的内容保持为:
Sleeping...
我检查了Process
的Javadoc,它没有解释这种行为。然后,我使用以下代码检查fork
,execlp
和waitpid
系统调用的行为。它显示了相同的行为。
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
static void err_sys(const char* msg) {
printf("%s\n", msg);
exit(1);
}
int main(void) {
pid_t pid;
if ((pid = fork()) < 0) {
err_sys("fork error");
} else if (pid == 0) {
if (execlp("/home/jing/code/lintcode/child.sh", "child.sh", (char *)0) < 0)
err_sys("execlp error");
}
if (waitpid(pid, NULL, 0) < 0)
err_sys("wait error");
exit(0);
}
我在Ubuntu 14.04上使用Oracle JDK 1.8。 uname -a
生成:
Linux jinglin 3.13.0-108-generic #155-Ubuntu SMP Wed Jan 11 16:58:52 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
任何人都可以对waitFor
和waitpid
Does Process.waitFor() make the process reliant on the java parent?在MAC平台上提出了类似的问题。但它缺乏细节。所以我在这里向我的环境提出这个问题。
答案 0 :(得分:3)
除了将父进程保留在前台之外,waitPid()
没有什么特别之处。
如果您分叉然后等待孩子完成,那么您有一个(简化的)流程树,如下所示:
─┬= 1 init
└─┬= 2 bash --login
└─┬= 3 java code
└─── 4 bash child.sh
java
是终端中的前台进程,子进程位于其进程组中。
当你点击^ C时,整个前台进程组被终止。 1
如果您不等待,那么首先您的进程树与上面的进程树相同。 java
进程终止,子进程成为进程树根处的进程的子进程。
─┬= 1 init
├──= 2 bash --login
└─── 4 bash child.sh
子进程完成执行并正常终止。
1 进程组收到SIGINT,默认操作将终止。但是,可以安装不同的信号处理程序。