是否可以为我没有启动的进程创建java.lang.Process实例?

时间:2017-07-10 10:36:12

标签: java process selenium-chromedriver

我有一个进程(在Windows上名为chromedriver.exe),这是在我创建Selenium Chrome Driver的新实例时创建的。

所以我不是自己开始这个过程,但是如果可能的话,我想要一个表示该过程的java.lang.Process实例。

我想创建这样的实例的原因是我想要在Process.waitFor()发出(如果在Windows上)Runtime.getRuntime().exec("taskkill /F /IM chromedriver.exe")之后,要求Process等待该进程实际终止。

我不能仅针对此特定需求引入对第三方库的新依赖。我可以使用Apache Commons中的任何内容。

所以问题是:我的代码是否有办法让WebDriver.quit()实例代表一个未从我的代码启动的正在运行的进程?

我希望能够杀死该进程的原因是像JVM崩溃这样的突然终止可能不会让exec("taskkill...")终止进程。因此,在创建导致进程启动的ChromeDriver实例之前,我想要杀死任何可能已存在的此类进程。

我在Windows上使用killall来终止进程的原因(我在Linux上使用Process)是我到目前为止找到的唯一方法,但是如果有可能的话为了获得代表该进程的Process.destroy()实例,我还尝试使用observeOn来查看its description“杀死子进程”中提到的“子进程”是指该进程。 / p>

1 个答案:

答案 0 :(得分:3)

简而言之,不是Java≤8,而是可以使用Java 9 java.lang.ProcessHandle

Java中的Process并不是为任意操作系统进程建模,而是实际建模java进程的子进程,因此无法连接到另一个正在运行的进程,并希望得到Process的所有功能:

  

类Process提供了从进程执行输入,执行输出到进程,等待进程完成,检查进程的退出状态以及销毁(杀死)进程的方法。

如您所见,输入和输出要求您的java进程在其他进程的stdin / stdout / stderr上拥有句柄,这只对子进程有意义。该文档还提到了“子进程”,因此暗示它是一个子进程。

在Java 9中,doc明确地以:

开头
  

流程提供对ProcessBuilder.startRuntime.exec启动的本机流程的控制。

但是Java 9也带来了ProcessHandle,这正是你所需要的:

  

ProcessHandle标识并提供对本机进程的控制。可以监视每个单独的过程的活跃度,列出其子项,获取有关该过程的信息或将其销毁。相比之下,Process实例由当前进程启动,并且还提供对进程输入,输出和错误流的访问。

因此,如果您可以使用Java 9运行测试,则可以尝试使用ProcessHandle.allProcesses()查找所需的进程,然后使用.destroy()将其终止,并使用{{3}监视其活跃度},或使用isAlive()

Optional<ProcessHandle> optional = ProcessHandle.allProcesses().filter(process -> {
    Optional<String> command = process.info().command();
    return command.isPresent() && command.get().equals("Chromedriver.exe");
}).findFirst();
if (optional.isPresent()) {
    ProcessHandle processHandle = optional.get();
    System.out.println("Killing process " + processHandle.pid());
    processHandle.destroy();
    try {
        System.out.println("Waiting for process " + processHandle.pid() + " to exit...");
        processHandle.onExit().get();
        System.out.println("Done !");
    } catch (InterruptedException|ExecutionException e) {
        e.printStackTrace();
    }
}

话虽如此,如果你真的想,你可以自己创建一个Process的子类,它将提供有限的功能(即没有关于I / O,只有waitFor和{{1 }}&amp; such)。

以下是一个可怕的示例,使用来自onExit()的想法快速入侵Windows实施。

  • 使用destroy
  • 按名称查找流程
  • tasklist /FO CSV /FI "IMAGENAME eq Chromedriver.exe", to get the PID
  • 杀死它
  • 等待它以使用taskkill
  • 的轮询循环结束

Linux版本使用tasklist /FO CSV /FI "PID eq ..."pgrepkill

请注意,将它包装为/proc/{pid}/的实际实例并不是很有用,因此我将关注点与实现Windows所需功能的工具类以及{{1}的子类分开了。实现为练习,以显示可能的内容,以及不可能的内容(代码中的详细信息)。因此,如果您需要,请更好地直接使用java.lang.Process,而不是Process

(我在另一个过程中对此进行了测试,我不能代表ProcessTool,您可能需要调整一些细节)

DummyProcess