为什么在使用waitFor的情况下查杀JVM也会终止它的subprocess呢?

如果不使用waitFor ,则杀死JVM对其subprocess没有影响。 这是一个例子。

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 ps -ef | grep 'child.sh' | grep -v grep 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命令来validationchild.shsubprocess正在运行。 然后我发出Ctrl-C ,JVM终止。 现在运行上面的grep命令什么也没有显示。 log文件的内容保持为:

 Sleeping... 

我已经检查了Process的Javadoc,它不能解释这种行为。 然后我使用下面的代码来检查forkexeclpwaitpid系统调用的行为。 它显示了相同的行为。

 #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 

任何人都可以解释waitForwaitpid这个效果吗?

Process.waitFor()是否依赖于java父进程? 在MAC平台上提出类似的问题。 但它缺乏细节。 所以我在这里为我的环境问这个问题。

关于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,默认行为是终止的。 但是,可能会安装不同的信号处理程序。