如何在没有Java 9+非法访问警告的情况下从Process获取pid?

Oli*_*din 9 java reflection pid process java-9

我需要为进程I启动获取底层OS 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;
}
Run Code Online (Sandbox Code Playgroud)

它有效,但这种方法有几个问题,一个是你需要在Windows上做额外的工作,因为特定于Windows的Process子类不存储"pid"字段而是存储"句柄"字段(所以你需要做获得实际pid的一点JNA,另一个是从Java 9开始,它触发了一系列可怕的警告,例如"警告:发生了非法的反射访问操作".

所以问题是:有没有更好的方法(干净,操作系统独立,保证不会在未来的Java版本中打破)来获得pid?难道这首先不应该被Java暴露出来吗?

Nam*_*man 7

您可以使用Process#pidJava9 中的介绍,其示例如下:

ProcessBuilder pb = new ProcessBuilder("echo", "Hello World!");
Process p = pb.start();
System.out.printf("Process ID: %s%n", p.pid());
Run Code Online (Sandbox Code Playgroud)

该方法的文档如下:

* Returns the native process ID of the process.
* The native process ID is an identification number that the operating
* system assigns to the process.
Run Code Online (Sandbox Code Playgroud)

并且同样值得注意

* @throws UnsupportedOperationException if the Process implementation
*         does not support this operation
Run Code Online (Sandbox Code Playgroud)

  • 对Java 9的一点点补充.请注意,如果平台不支持公开进程ID,则可能会触发"UnsupportedOperationException". (3认同)
  • 对它支持的平台的一般指导不太确定.但是,我可以确认在Mac上使用它.@OlivierGérardin (2认同)
  • 您可以假设它将适用于Reflection hack过去工作的所有平台(因为这是pid可用性的标志).但是也值得研究方法`toHandle()`和`info()`以及它们返回的[`ProcessHandle`](https://docs.oracle.com/en/java/javase/11/docs/api/ java.base/java/lang/ProcessHandle.html)和[`ProcessHandle.Info`](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang /ProcessHandle.Info.html)API.也许,您不再需要pid,因为无论您想用它做什么,现在都可以直接使用Java API完成... (2认同)