简体   繁体   中英

How to get the path to the currently running Java command-line path? (before symbolic links)

I've written a program that outputs a usage hint. It currently echos back the path to the main jar file as was originally entered on the command line.

Usage: java -jar path/to/MyJar.jar <params> ...

For completeness, I'd like to make sure that the java bit is echoed back as well, as there are various ways to access java , (beyond just the word java , and shorter than the canonical path to /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

How can I determine what command-line was used to evoke the JVM?
I would like the original command-line value, prior to evaluating symbolic links.

I'm not using System.getProperty("java.home") because it has no respect for the original command-line value, just the final 'canonical' location of the JVM. (Having a usage note like Usage: /us/opt/java-1.8.0-u123/jre/bin/java -jar ... would be rather verbose,
especially when using simple java on the command line.)

Is determining the command-line location of java possible using pure Java code?
(ie not using a wrapper script in bash )

Use following command

jps -mlvV

This should print everything about running java processes.

Where as ps -e should give you executable path.

Following is pure Java solution, it doesn't print the actual command used to execute the application but it produces a command which will have the same effect.

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;
    }
}

Note: It will work with plain java projects or normal JARS, however it will not work with special classloading like WAR, OSGI or Spring Boot's classloading.

I used the findMainClass() method from this answer https://stackoverflow.com/a/8275751/5343269

Use this System property in code

System.getProperty("java.home");

This will return Installation directory for Java Runtime Environment (JRE)

More info here

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM