【问题标题】:Windows JDK8: When will the windows system reuse the handle value of a process object?Windows JDK8:windows系统什么时候会重用进程对象的句柄值?
【发布时间】:2019-04-22 06:54:57
【问题描述】:

环境

Windows 上的 jdk8

步骤

  1. 使用ProcessBuilder 创建一个Process 实例,并使用进程的输出执行一些任务。
  2. 致电waitFor() 等待此过程完成。
  3. 使用jna+cmd强制终止进程。我在 finally 块中执行此操作,以确保进程始终终止。
Field f = process.getClass().getDeclaredField("handle");
f.setAccessible(true);
long handleValue = f.getLong(process);
WinNT.HANDLE handle = new WinNT.HANDLE();
handle.setPointer(Pointer.createConstant(handleValue));
Kernel32 kernel = Kernel32.INSTANCE;
int pid = kernel.GetProcessId(handle);
Process killPr = Runtime.getRuntime().exec("cmd /c taskkill /pid " + pid + " /f /t");
killPr.waitFor();
killPr.destroy();

问题

执行上述步骤是否安全?我会在第 3 步中杀死另一个不相关的进程吗?我调试并注意到ProcessImplhandle 值在进程退出后仍然有效。我担心windows系统会在退出真实进程进程对象没有被jvm回收时重用相同的句柄。

【问题讨论】:

  • 无论如何,当您通过 JNA 使用本机调用时,为什么不直接调用 TerminateProcess 而不是启动运行命令行解释器的外部进程,执行 taskkill 命令最终执行所需的操作打电话?
  • @Holger 我不确定TerminateProcess 是否也会杀死所有子进程。 api 文档说此方法将终止指定进程及其所有线程taskkill/t 参数将执行此操作,请参阅 this page
  • 好吧,我对 Windows API 没有那么深入,但很明显,taskkill 必须调用一个函数,因为taskkill 命令只是软件。因此,无论taskkill 使用什么函数,直接通过 JNA 调用都是更简单的选择。最后,您想销毁Process,如果您认为,在其上调用destroy() 是不够的,那么启动新的Process 并最终依靠在其上调用destroy() 是一种扭曲的解决方案。

标签: windows winapi java-8 process win32-process


【解决方案1】:

Process handle becomes available for reuse only after the last handle to the process is closed。只要你能确保process 不被清理,通过PID 杀死进程就可以了。此外,由于您已经在使用 JNA,因此有更简洁的方法可以终止该进程,请参阅kernel32.TerminateProcess

process 的句柄将在 finalize 中关闭,Process 类也会调用destroy(),这也会触发TerminateProcess 调用。大多数情况下,你不必做你正在做的事情。调用destroy 后跟waitFor 应该可以完成这项工作。

【讨论】:

  • 感谢您的快速回复。如果我理解正确的话,只要 jvm 不回收 ProcessImpl java 对象,实际系统进程的句柄就不会关闭?
猜你喜欢
  • 1970-01-01
  • 2016-10-16
  • 2018-12-12
  • 2015-03-13
  • 2018-11-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-21
相关资源
最近更新 更多