我写了一个输出用法提示的程序。它当前回到了最初在命令行上输入的主jar
文件的路径。
Usage: java -jar path/to/MyJar.jar <params> ...
为了完整起见,我想确保java
位也得到回复,因为有多种方式可以访问java
,(除了java
这个词之外,比规范路径短到/us/opt/java-1.8.0-u123/bin/java
)
Usage: /us/opt/java7/bin/java -jar MyJar.jar <params> ...
Usage: ./bin/java -jar MyJar.jar <params> ...
Usage: java -jar MyJar.jar <params> ...
# whatever the user typed in
如何确定用于唤起JVM的命令行?
在评估符号链接之前,我想要原始的命令行值。
我没有使用System.getProperty("java.home")
因为它不尊重原始命令行值,只是JVM的最终“规范”位置。 (像Usage: /us/opt/java-1.8.0-u123/jre/bin/java -jar ...
这样的使用说明会相当冗长,
特别是在命令行中使用简单的java
时。)
使用纯Java代码确定java
的命令行位置是什么?
(即不使用bash
中的包装脚本)
答案 0 :(得分:0)
使用以下命令
jps -mlvV
这应该打印有关运行java进程的所有内容。
ps -e
应该为您提供可执行路径。
以下是纯Java解决方案,它不会打印用于执行应用程序的实际命令,但它会生成一个具有相同效果的命令。
import java.io.File;
import java.lang.management.ManagementFactory;
import java.util.List;
import java.util.Map.Entry;
import java.util.stream.Collectors;
public class Main {
public static void main(String[] args) {
System.out.println("Printing command");
createCommand();
}
public static void createCommand() {
try {
String jvm = getJvmExecutable();
String mainClassName = findMainClass();
String processDir = System.getProperty("user.dir");
String arguments = getArguments();
String classpath = ManagementFactory.getRuntimeMXBean().getClassPath();
String command = String.format("cd %s & %s %s -classpath %s %s",processDir, jvm, arguments, classpath, mainClassName);
System.out.println(command);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
private static String getJvmExecutable() {
String jvm = "";
jvm = System.getProperty("java.home");
jvm += File.separator + "bin" + File.separator + "java";
jvm = '"' + jvm + '"';
return jvm;
}
private static String getArguments() {
List<String> argsList = ManagementFactory.getRuntimeMXBean().getInputArguments();
String args = argsList.stream().collect(Collectors.joining(" "));
return args;
}
public static String findMainClass() throws ClassNotFoundException{
for (Entry<Thread, StackTraceElement[]> entry : Thread.getAllStackTraces().entrySet()) {
Thread thread = entry.getKey();
if (thread.getThreadGroup() != null && thread.getThreadGroup().getName().equals("main")) {
for (StackTraceElement stackTraceElement : entry.getValue()) {
if (stackTraceElement.getMethodName().equals("main")) {
try {
Class<?> c = Class.forName(stackTraceElement.getClassName());
Class[] argTypes = new Class[] { String[].class };
//This will throw NoSuchMethodException in case of fake main methods
c.getDeclaredMethod("main", argTypes);
return stackTraceElement.getClassName();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
}
}
}
return null;
}
}
注意:它适用于普通的java项目或普通的JARS,但它不适用于特殊的类加载,如WAR,OSGI或Spring Boot的类加载。
我使用了此答案https://stackoverflow.com/a/8275751/5343269
中的findMainClass()
方法
答案 1 :(得分:0)