查找JDK路径并将其存储为Java中的字符串

时间:2013-03-31 02:04:49

标签: path java

我想在多个操作系统上找到JDK路径。

我不确定这是否有一种很好的方法,因为我一直在尝试和失败。

对于Windows,它会是这样的 - C:\Program Files\Java\jdk1.7.0_07或者这个 C:\Program Files(x86)\Java\jdk1.7.0_07

对于Linux,它将是这样的 - /usr/java/jdk1.7.0_07

我希望这适用于安装的任何JDK版本,因此Java \ jdk之后的数字无关紧要。

我将使用System.setProperty("java.home", path);

基本上,我要做的是当我运行我的程序时,将java.home设置为当前机器上安装的JDK,但获得JDK路径证明是非常困难的,任何解决方案?

14 个答案:

答案 0 :(得分:7)

您可以通过查看javac的安装位置来查找JDK路径。 假设“javac”在系统的环境路径中,那么您可以通过将“where javac”传递给代码来检索路径,例如以下

public static String getCommandOutput(String command)  {
    String output = null;       //the string to return

    Process process = null;
    BufferedReader reader = null;
    InputStreamReader streamReader = null;
    InputStream stream = null;

    try {
        process = Runtime.getRuntime().exec(command);

        //Get stream of the console running the command
        stream = process.getInputStream();
        streamReader = new InputStreamReader(stream);
        reader = new BufferedReader(streamReader);

        String currentLine = null;  //store current line of output from the cmd
        StringBuilder commandOutput = new StringBuilder();  //build up the output from cmd
        while ((currentLine = reader.readLine()) != null) {
            commandOutput.append(currentLine);
        }

        int returnCode = process.waitFor();
        if (returnCode == 0) {
            output = commandOutput.toString();
        }

    } catch (IOException e) {
        System.err.println("Cannot retrieve output of command");
        System.err.println(e);
        output = null;
    } catch (InterruptedException e) {
        System.err.println("Cannot retrieve output of command");
        System.err.println(e);
    } finally {
        //Close all inputs / readers

        if (stream != null) {
            try {
                stream.close();
            } catch (IOException e) {
                System.err.println("Cannot close stream input! " + e);
            }
        } 
        if (streamReader != null) {
            try {
                streamReader.close();
            } catch (IOException e) {
                System.err.println("Cannot close stream input reader! " + e);
            }
        }
        if (reader != null) {
            try {
                streamReader.close();
            } catch (IOException e) {
                System.err.println("Cannot close stream input reader! " + e);
            }
        }
    }
    //Return the output from the command - may be null if an error occured
    return output;
}

返回的字符串将是javac的确切位置,因此您可能需要额外的处理来获取javac所在的目录。您需要区分Windows和其他操作系统

public static void main(String[] args) {

    //"where" on Windows and "whereis" on Linux/Mac
    if (System.getProperty("os.name").contains("win") || System.getProperty("os.name").contains("Win")) {
        String path = getCommandOutput("where javac");
        if (path == null || path.isEmpty()) {
            System.err.println("There may have been an error processing the command or ");
            System.out.println("JAVAC may not set up to be used from the command line");
            System.out.println("Unable to determine the location of the JDK using the command line");
        } else {
            //Response will be the path including "javac.exe" so need to
            //Get the two directories above that
            File javacFile = new File(path);
            File jdkInstallationDir = javacFile.getParentFile().getParentFile();
            System.out.println("jdk in use at command line is: " + jdkInstallationDir.getPath());
        }//else: path can be found
    } else {
        String response = getCommandOutput("whereis javac");
        if (response == null) {
            System.err.println("There may have been an error processing the command or ");
            System.out.println("JAVAC may not set up to be used from the command line");
            System.out.println("Unable to determine the location of the JDK using the command line");
        } else {
            //The response will be "javac:  /usr ... "
            //so parse from the "/" - if no "/" then there was an error with the command
            int pathStartIndex = response.indexOf('/');
            if (pathStartIndex == -1) {
                System.err.println("There may have been an error processing the command or ");
                System.out.println("JAVAC may not set up to be used from the command line");
                System.out.println("Unable to determine the location of the JDK using the command line");
            } else {
                //Else get the directory that is two above the javac.exe file
                String path = response.substring(pathStartIndex, response.length());
                File javacFile = new File(path);
                File jdkInstallationDir = javacFile.getParentFile().getParentFile();
                System.out.println("jdk in use at command line is: " + jdkInstallationDir.getPath());
            }//else: path found
        }//else: response wasn't null
    }//else: OS is not windows
}//end main method

注意:如果方法返回null / error并不意味着javac不存在 - 很可能是javac不在Windows上的PATH环境变量中,因此无法使用此方法找到。这在Unix上不太可能,因为Unix通常会自动将jdk / bin目录添加到PATH。 此外,这将返回当前在命令行中使用的javac版本,不一定是安装的最新版本。如果是安装了7u12和7u13但是命令提示符设置为使用7u12,那就是将返回的路径。

仅在多台Windows计算机上进行了测试,但在这些计算机上运行良好。

希望这有帮助。

答案 1 :(得分:2)

JAVA_HOME应该指向所有操作系统中的JDK安装路径和JRE_HOME到JRE安装路径

答案 2 :(得分:2)

我不知道重要的是什么。

public class Main implements Serializable{
    public static void main(String[] args) {
        System.out.println(System.getenv("JAVA_HOME"));
    }
}

在Windows上打印C:\Program Files\Java\jdk1.7.0,在unix系统上打印/usr/java/jdk1.7.0_13。如果未设置环境属性JAVA_HOME,则返回null。你应该认为java没有正确安装/配置,因此你的应用程序无法运行。

答案 3 :(得分:1)

System.getProperties()中的JAVA_HOME变量引用JRE而不是JDK。您应该能够找到JDK:

Map<String, String> env = System.getenv();
 for (String envName : env.keySet())
 {
 System.out.format("%s=%s%n",
 envName,
 env.get(envName));
 }

答案 4 :(得分:0)

System.getProperty(“java.home”)对你不够好?

如果它以“jre”结尾,你就会知道这是jre,你可以尝试走路并找到根文件夹并检查只有JDK才能确定的不同文件。

答案 5 :(得分:0)

System.getProperties()中的JAVA_HOME变量引用JRE而不是JDK。 您应该能够找到JDK:

Map<String, String> env = System.getenv();
        for (String envName : env.keySet())
        {
            System.out.format("%s=%s%n",
                    envName,
                    env.get(envName));
        }

答案 6 :(得分:0)

以下是我对此的看法: 您可以选择要安装jdk的位置,也可以安装多个jdk。所以我不认为可以有一个标准变量。

让我们假设标准目录结构已用于安装jdk。在这种情况下,jre和jdk安装将位于同一目录下。

因此,一旦获得System.getProperty(“java.home”),则只需搜索目录即可。

希望有所帮助。

答案 7 :(得分:0)

上帝这是如此令人费解,但我完成了。虽然它只在Windows上进行过测试。

import java.io.File;

public class Main {
    public static void main(String[] args) {
        String JDK_VERSION = "jdk" + System.getProperty("java.version"); // finds the JDK version currently installed
        String PATH_VARIABLE = System.getenv("PATH"); // finds all the system environment variables

        // separates all the system variables
        String[] SYSTEM_VARIABLES = PATH_VARIABLE.split(";");

        // this object helps build a string
        StringBuilder builder = new StringBuilder();

        // loop through all the system environment variables
        for (String item : SYSTEM_VARIABLES) {
            // if the system variable contains the JDK version get it! (all lower case just to be safe)
            if (item.toLowerCase().contains(JDK_VERSION.toLowerCase())) {
                // adds the JDK path to the string builder
                builder.append(item);
            }
        }

        // stores the JDK path to a variable
        String result = builder.toString();
        // turns the path, which was a string in to a usable file object.
        File JDK_PATH = new File(result);
        // since the path is actually in the JDK BIN folder we got to go back 1 directory
        File JDK_PATH_FINAL = new File(JDK_PATH.getParent());
        // prints out the result
        System.out.println(JDK_PATH_FINAL);
    }
}

基本上做的是获取所有系统变量并查找其中一个是否包含java版本(我获取JDK路径的方式)。由于系统变量路径实际上位于JDK bin文件夹中,因此它将JDK路径String转换为File并将一个文件夹返回到JDK目录。

答案 8 :(得分:0)

您可以使用java的getenv函数来获取PATH。

答案 9 :(得分:0)

我认为你最好也是最可靠的选择(因为Java_home等不需要声明为了获得JVM,我可以在脚本中使用完整路径并启动Java。

获取java进程ID,使用API​​获取该进程的路径。

这不是一个完整的解决方案,而是指导方针。

如果您确定在所有Java应用程序中准确设置了java.home,那么可以按照其他答案中的描述使用它

帮助获取进程ID的路径How do I get the path of a process in Unix / Linux

同样需要Windows。我确信它已经在工具中看到了

答案 10 :(得分:0)

如果您想在程序中编译程序,为什么不采取以下方法:

    JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
    compiler.run(/* your arguments here */);

完整说明here

答案 11 :(得分:0)

最好的办法是查看System.getProperty("sun.boot.class.path")的值,将其标记为System.getProperty("path.separator")的值,并查找标准的JDK JAR文件。

例如,在我的系统上,我得到(为了便于阅读而被截断):

sun.boot.class.path = "/System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Classes/jsse.jar:/System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Classes/laf.jar:

path.separator = ":"

这很容易让我知道所有系统JAR文件都在/System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Classes/

不幸的是,这并不是非常有用,因为我正在运行OS X,它具有非标准的Java安装结构。如果你没有针对OS X机器,你可以通过我们刚刚计算的值来计算安装目录(我相信它是值的父目录)。

如果您还想支持OS X,则可能必须使用os.name系统属性并编写add-hoc代码。

答案 12 :(得分:0)

好奇......如果你想在运行时编译其他java代码,为什么不使用Java Compiler API?除非您使用Runtime exec()

调用java编译器

答案 13 :(得分:0)

在考虑@Nicolas Rinaudo 的回答后,我开始编写一些只检查系统属性中任何路径的东西。 我在 Windows 10 和 Linux (Debian 9) 上对此进行了测试,效果很好。

private static final Pattern JDK_REGEX = Pattern.compile("jdk[0-9].[0-9].[0-9]_(.*?)" + StringEscapeUtils.escapeJava(File.separator));

public static String findJDKPath() {
        Enumeration<Object> properties = System.getProperties().elements();
        List<String> possibilities = new ArrayList<>();
        String separator = System.getProperty("path.separator");
        while(properties.hasMoreElements()) {
            Object element = properties.nextElement();
            if (!(element instanceof String)) {
                continue;
            }
            String string = (String) element;
            String[] split = string.split(separator);
            for(String s : split) {
                if (s.contains("jdk") && s.contains(File.separator)) {
                    possibilities.add(s);
                }
            }
        }
        for(String s : possibilities) {
            Matcher matcher = JDK_REGEX.matcher(s);
            if (matcher.find()) {
                String group = matcher.group();
                return s.substring(0, s.indexOf(group) + group.length());
            }
        }
        return null;
    }
相关问题