如果不使用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.sh
subprocess正在运行。 然后我发出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
这个效果吗?
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,默认行为是终止的。 但是,可能会安装不同的信号处理程序。