如果使用waitFor,为什么kill JVM也会终止其子进程?

时间:2017-02-10 07:10:05

标签: 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 = 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,它没有解释这种行为。然后,我使用以下代码检查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

的影响做出解释

Does Process.waitFor() make the process reliant on the java parent?在MAC平台上提出了类似的问题。但它缺乏细节。所以我在这里向我的环境提出这个问题。

1 个答案:

答案 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,默认操作将终止。但是,可以安装不同的信号处理程序。