Java 如果使用了waitFor,为什么杀死JVM也会终止其子进程?
如果未使用Java 如果使用了waitFor,为什么杀死JVM也会终止其子进程?,java,linux,jvm,Java,Linux,Jvm,如果未使用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 = Runti
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代码
后,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代码
之后,我使用上面的grep
命令来验证child.sh
子进程是否正在运行。然后我发出Ctrl-C
,JVM终止。现在运行上面的grep
命令不会显示任何内容。而日志
文件的内容保持为:
Sleeping...
我已经检查了进程
的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);
}
有人能解释一下waitFor
和waitpid
的这种效果吗
在MAC平台上询问类似的问题。但它缺乏细节。因此,我在这里针对我的环境问了这个问题。waitPid()没有什么特别之处,只是将父进程保持在前台
如果您使用fork,然后等待子进程完成,则会有一个(简化的)进程树,如下所示:
─┬= 1 init
└─┬= 2 bash --login
└─┬= 3 java code
└─── 4 bash child.sh
java
是终端中的前台进程,子进程在其进程组中
当您点击^C时,整个前台进程组将被终止
如果您不等待,那么首先您的流程树与上面的流程树相同。
java
进程终止,子进程成为进程树根的子进程
─┬= 1 init
├──= 2 bash --login
└─── 4 bash child.sh
子进程完成执行并正常终止
1流程组收到一个SIGINT,默认操作是终止该SIGINT。但是,可能会安装不同的信号处理程序。您确定吗?控制终端对于涉及的所有三个过程都是相同的,并且它从不关闭。True。但是它们是如何终止的呢?内核将SIGINT发送到终端中会话的前台进程组。
─┬= 1 init
├──= 2 bash --login
└─── 4 bash child.sh