类似于 Yoda 的“improved”答案,但有进一步的改进(功能性、可读性和可测试性)。它现在可以安全运行,并且可以根据给定的程序参数数量重新启动。
- 没有
JAVA_TOOL_OPTIONS 选项的累积。
- 自动查找主类。
- 继承当前的标准输出/标准错误。
public static void main(String[] args) throws Exception {
if (args.length == 0)
return;
else
args = Arrays.copyOf(args, args.length - 1);
List<String> command = new ArrayList<>(32);
appendJavaExecutable(command);
appendVMArgs(command);
appendClassPath(command);
appendEntryPoint(command);
appendArgs(command, args);
System.out.println(command);
try {
new ProcessBuilder(command).inheritIO().start();
} catch (IOException ex) {
ex.printStackTrace();
}
}
private static void appendJavaExecutable(List<String> cmd) {
cmd.add(System.getProperty("java.home") + File.separator + "bin" + File.separator + "java");
}
private static void appendVMArgs(Collection<String> cmd) {
Collection<String> vmArguments = ManagementFactory.getRuntimeMXBean().getInputArguments();
String javaToolOptions = System.getenv("JAVA_TOOL_OPTIONS");
if (javaToolOptions != null) {
Collection<String> javaToolOptionsList = Arrays.asList(javaToolOptions.split(" "));
vmArguments = new ArrayList<>(vmArguments);
vmArguments.removeAll(javaToolOptionsList);
}
cmd.addAll(vmArguments);
}
private static void appendClassPath(List<String> cmd) {
cmd.add("-cp");
cmd.add(ManagementFactory.getRuntimeMXBean().getClassPath());
}
private static void appendEntryPoint(List<String> cmd) {
StackTraceElement[] stackTrace = new Throwable().getStackTrace();
StackTraceElement stackTraceElement = stackTrace[stackTrace.length - 1];
String fullyQualifiedClass = stackTraceElement.getClassName();
String entryMethod = stackTraceElement.getMethodName();
if (!entryMethod.equals("main"))
throw new AssertionError("Entry point is not a 'main()': " + fullyQualifiedClass + '.' + entryMethod);
cmd.add(fullyQualifiedClass);
}
private static void appendArgs(List<String> cmd, String[] args) {
cmd.addAll(Arrays.asList(args));
}
V1.1 修正:如果未设置 JAVA_TOOL_OPTIONS 则为空指针
例子:
$ java -cp Temp.jar Temp a b c d e
[/usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java, -cp, Temp.jar, Temp, a, b, c, d]
[/usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java, -cp, Temp.jar, Temp, a, b, c]
[/usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java, -cp, Temp.jar, Temp, a, b]
[/usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java, -cp, Temp.jar, Temp, a]
[/usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java, -cp, Temp.jar, Temp]
$