这是一种确定运行当前 JVM 的 java 可执行文件的方法ProcessHandle.current().info().command()
。
ProcessHandle
API 还应该允许获取参数。如果可用,此代码将它们用于新的 JVM,仅将当前类名替换为另一个示例类。(如果您不知道其名称,则在参数中查找当前主类会变得更加困难,但在此演示中,它只是“this”类。也许您想重用相同的 JVM 选项或其中一些选项,而不是程序论据。)
但是,对我来说(openjdk 版本 11.0.2,Windows 10),ProcessInfo.arguments()
是空的,所以回退else
路径被执行。
package test;
import java.lang.ProcessBuilder.Redirect;
import java.lang.management.ManagementFactory;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class TestStartJvm {
public static void main(String[] args) throws Exception {
ProcessHandle.Info currentProcessInfo = ProcessHandle.current().info();
List<String> newProcessCommandLine = new LinkedList<>();
newProcessCommandLine.add(currentProcessInfo.command().get());
Optional<String[]> currentProcessArgs = currentProcessInfo.arguments();
if (currentProcessArgs.isPresent()) { // I know about orElse, but sometimes isPresent + get is handy
for (String arg: currentProcessArgs.get()) {
newProcessCommandLine.add(TestStartJvm.class.getName().equals(arg) ? TargetMain.class.getName() : arg);
}
} else {
System.err.println("don't know all process arguments, falling back to passed args array");
newProcessCommandLine.add("-classpath");
newProcessCommandLine.add(ManagementFactory.getRuntimeMXBean().getClassPath());
newProcessCommandLine.add(TargetMain.class.getName());
newProcessCommandLine.addAll(List.of(args));
}
ProcessBuilder newProcessBuilder = new ProcessBuilder(newProcessCommandLine).redirectOutput(Redirect.INHERIT)
.redirectError(Redirect.INHERIT);
Process newProcess = newProcessBuilder.start();
System.out.format("%s: process %s started%n", TestStartJvm.class.getName(), newProcessBuilder.command());
System.out.format("process exited with status %s%n", newProcess.waitFor());
}
static class TargetMain {
public static void main(String[] args) {
System.out.format("in %s: PID %s, args: %s%n", TargetMain.class.getName(), ProcessHandle.current().pid(),
Stream.of(args).collect(Collectors.joining(", ")));
}
}
}
在ProcessHandle
Java 9 中添加之前,我做了这样的事情来查询当前 JVM 的命令行:
- 让用户传递或配置一个“PID to command-line”命令模板;在 Windows 下,这可能是
wmic process where 'processid=%s' get commandline /format:list
.
- 使用 确定 PID
java.lang.management.ManagementFactory.getRuntimeMXBean().getPid()
。
- 扩展命令模板;执行; 解析它的输出。