在Java中获取子进程ID

15

我是这样创建子进程的:

String command = new String("some_program");

Process p = Runtime.getRuntime().exec(command);

我该如何获取子进程的 id?

附:我正在 Linux 上工作。


在这种情况下,使用字符串命令 =“some_program”更好。 - pstanton
这不是真正的代码,只是一个片段来描述问题。 - Pawka
6个回答

29
这个还没有公开的API(参见https://bugs.java.com/bugdatabase/view_bug?bug_id=4244896),但有一些解决方法。
第一个解决方法是使用外部程序,比如ps,并使用Runtime.exec()调用它来获取pid :)
另一个解决方法是基于java.lang.Process类是抽象类的事实,实际上你会得到一个具体的子类,具体取决于你的平台。在Linux上,你会得到一个java.lang.UnixProcess,它有一个私有字段int pid。使用反射,你可以轻松地获取这个字段的值:
Field f = p.getClass().getDeclaredField("pid");
f.setAccessible(true);
System.out.println( f.get( p ) );

好问题!我想知道为什么这样的错误已经存在了10多年而没有解决方案? - Pascal Thivent
3
可能是因为Sun希望您留在JVM内部。 - Thorbjørn Ravn Andersen
2
可能是因为请求涉及到java.lang.System。在那里放置PID会使其变成特定于平台,这是错误的。但UnixProcess没有隐藏它的理由。 - Bozho
谢谢,运作得非常完美。我刚刚在sun.com上提交了一个RFE来解决这个问题。 - Pawka
@Bozho 嗯,你实际上不应该去操作一个平台特定的类,比如 UnixProcess - Pascal Thivent
显示剩余2条评论

1

这里开始

public static void main(String[] args) throws IOException {
    byte[] bo = new byte[100];
    String[] cmd = {"bash", "-c", "echo $PPID"};
    Process p = Runtime.getRuntime().exec(cmd);
    p.getInputStream().read(bo);
    System.out.println(new String(bo));
}

我之前找到过那篇文章,但它并不适合我。我无法准备或修改子进程程序以输出PID。 - Pawka

1

我之前尝试过这个(但失败了)。最终我将我的命令包装在一个 shell 脚本中,并将 pid 写入文件。虽然不是最好的解决方案,但它帮我克服了这个障碍。


这是我最初的想法,但它并不适合我。 "命令" 可以是几乎任何程序,而不是由我准备的。无论如何,谢谢。 - Pawka

1

其实没有官方文档提供的方法,但是进程实现类是UNIXProcess,它有一个pid属性。因此,你可以使用反射来访问这个私有属性来获取ID。在谷歌上搜索,你会找到其他调用另一个shell来获取ps输出的技巧。不过都不是很简单。


0

鉴于目前没有公共API可以获取pid

我们还可以采用以下技巧来获得pid
如果您使用Liberica JDK,否则,您可以检查是否可以使用相同的想法:

String pid = process.toString().substring(12, process.toString().indexOf(','));

以上代码的想法是,在检查ProcessImpl类中的toString()实现后。
@Override
public String toString() {
    return new StringBuilder("Process[pid=").append(pid)
            .append(", exitValue=").append(hasExited ? exitcode : "\"not exited\"")
            .append("]").toString();
}

缺点:

  • 这种方式依赖于实现!
  • 当您更改JDK时,可能需要更改解析器以获取pid

0

使用 Java 9,现在您可以直接获取 pid,因为它在 Process API 接口中已经定义。

process.pid();

Process接口的主要代码

/**
 * Returns the native process ID of the process.
 * The native process ID is an identification number that the operating
 * system assigns to the process.
 *
 * @implSpec
 * The implementation of this method returns the process id as:
 * {@link #toHandle toHandle().pid()}.
 *
 * @return the native process id of the process
 * @throws UnsupportedOperationException if the Process implementation
 *         does not support this operation
 * @since 9
 */
public long pid() {
    return toHandle().pid();
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接