【问题标题】:How to get the path to the currently running Java command-line path? (before symbolic links)如何获取当前运行的 Java 命令行路径的路径? (在符号链接之前)
【发布时间】:2016-07-29 04:12:23
【问题描述】:

我编写了一个输出使用提示的程序。它当前回显了最初在命令行中输入的主 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 中不使用包装脚本)

【问题讨论】:

  • 我想知道为什么投反对票。是因为问题不清楚还是因为它是重复的?我在询问之前进行了搜索,但我不断得到无法解决这个特定问题的结果。
  • 目前尚不清楚您是否知道其他选项,或者您正在尝试做的事情是链接问题中投票最多的答案无法做到的。
  • 好吧,我不知道链接的问题。现在我已经看过了,我将编辑我的问题以澄清。

标签: java command-line


【解决方案1】:

使用以下命令

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()方法

【讨论】:

  • 我正在寻找一个纯 Java 代码解决方案,以便应用程序可以生成自己的使用脚本。为此目的,exec 外部进程(例如 jpsps)似乎效率低下。
  • 我澄清了这个问题。我已经有了主类和 jar 的路径,但我正在寻找的是 java 的路径,它不是那么简洁。因此,如果用户键入java,则使用说明可以只是java。如果用户输入了一个符号链接,我就想要那个。我确实总是显示System.getProperty("java.home")返回的“完整路径”。
  • 我不确定我是否理解正确,机器上可能安装了多个版本的Java,这就是为什么我使用java.home来检索用于启动的JVM过程。
  • 我实际上并没有尝试获取 JVM 的“绝对”和“规范”路径。我想要用户输入的内容,可能只是单词java,或相对路径./mydir/bin/java,符号链接的绝对路径/usr/bin/java 或完整的规范路径。我不想总是反映完整的规范路径,我想反映输入的内容。
【解决方案2】:

在代码中使用这个系统属性

System.getProperty("java.home");

这将返回 Java 运行时环境 (JRE) 的安装目录

更多信息here

【讨论】:

  • 我已经澄清了这个问题。这个答案对我不起作用。
猜你喜欢
  • 2023-03-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-14
  • 2015-02-08
  • 1970-01-01
  • 2011-07-08
  • 2018-05-30
相关资源
最近更新 更多