如何在Java 9+中从进程中获取pid而不出现非法访问警告?

9

我需要获取我启动的进程的底层操作系统PID。 我现在使用的解决方案涉及通过反射访问私有字段,使用像这样的代码:

private long getLongField(Object target, String fieldName) throws NoSuchFieldException, IllegalAccessException {
    Field field = target.getClass().getDeclaredField(fieldName);
    field.setAccessible(true);
    long value = field.getLong(target);
    field.setAccessible(false);
    return value;
}

这种方法可以运行,但存在几个问题。其中一个问题是在Windows上需要额外的工作,因为Windows特定的Process子类不存储“pid”字段,而是存储“handle”字段(所以需要使用一些JNA来获取实际pid),另一个问题是从Java 9开始它会触发一堆可怕的警告,如“WARNING: An illegal reflective access operation has occurred”。
因此问题是:是否有更好的方法(清洁、与操作系统无关、保证在将来的Java版本中不会出现问题)来获取pid?这一点难道不应该首先由Java公开吗?
1个回答

7
你可以使用 Java9 中引入的 Process#pid,以下是一个示例:
ProcessBuilder pb = new ProcessBuilder("echo", "Hello World!");
Process p = pb.start();
System.out.printf("Process ID: %s%n", p.pid());

该方法的文档读取如下:
* Returns the native process ID of the process.
* The native process ID is an identification number that the operating
* system assigns to the process.

同样来自相同的,也值得注意

* @throws UnsupportedOperationException if the Process implementation
*         does not support this operation

3
Java 9的一个不错的小改进。请注意,如果平台不支持公开进程ID,则可能会触发“UnsupportedOperationException”。 - Mark Peters
2
对于它支持的平台的一般指导不是很确定。但是,我可以确认在Mac上肯定可以使用。@OlivierGérardin - Naman
2
您可以假设它将在所有以前Reflection hack可用的平台上工作(因为这是pid可用性的标志)。但是,值得注意的是查看toHandle()info()方法及其返回的ProcessHandleProcessHandle.Info API。也许,您不再需要pid,因为您想要使用它的任何操作现在都可以直接使用Java API完成... - Holger
@Holger 我将 pid 存储在文件中以管理长时间运行的作业,这是在 Unix 和类 Unix 操作系统下常见的模式,因此我确实需要 pid... - Olivier Gérardin
@OlivierGérardin 好的,那么你需要pid,但这正是这个新支持的用途。 - Holger
显示剩余2条评论

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