【问题标题】:Finding JDK path and storing it as a string in Java查找JDK路径并将其存储为Java中的字符串
【发布时间】:2013-03-21 11:22:53
【问题描述】:

我想在多个操作系统上查找 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 路径非常困难,有什么解决方案吗?

【问题讨论】:

  • 为什么要找JDK的路径?我很困惑为什么人们会想要这些信息。
  • 这就是JAVA_HOME 环境变量的用途!
  • 我用它来编译其他类。我的程序,编译其他程序。
  • 也许他正在尝试创建一种简单的方法来解决可能由此路径引起的一些问题。
  • 这个问题很模棱两可。可以安装许多 JDK,因此我们不是在谈论一个 JDK 路径,而是在谈论多个 JDK 路径。其次,您是否想找到当前正在执行您的代码的 java 二进制文件的路径?所以需要澄清一下,找到所有的JDK路径或者找到当前正在执行.class(做查找)的JDK的路径。

标签: path java


【解决方案1】:

在考虑了@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;
    }

【讨论】:

    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

      您最好的选择可能是查看 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 系统属性并编写附加代码。

      【讨论】:

        【解决方案4】:

        我不知道有什么大不了的。

        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 尚未正确安装/配置,因此您的应用程序无法运行。

        【讨论】:

          【解决方案5】:

          我认为你最好和最可靠的赌注(因为 Java_home 等不需要声明来启动 JVM,我可以在脚本中使用完整路径并启动 Java。

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

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

          如果您确定所有 java 应用程序中的 java.home 设置正确,则可以按照其他答案中的说明使用它

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

          同样需要windows。我确信它在那里,就像在工具中看到的那样

          【讨论】:

            【解决方案6】:

            如果你想在你的程序中编译程序为什么不直接采用以下方法:

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

            完整描述here

            【讨论】:

              【解决方案7】:

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

              【讨论】:

                【解决方案8】:

                天哪,这太令人费解了,但我完成了。虽然它只在 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 目录。

                【讨论】:

                • 安装时这不会一直有效,我可以更改路径并且分号不是所有操作系统的文件分隔符都使用常量
                【解决方案9】:

                您可以通过查看 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 机器上进行了测试,但在它们上运行良好。

                希望这会有所帮助。

                【讨论】:

                  【解决方案10】:

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

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

                  所以一旦你得到 System.getProperty("java.home") 然后简单地搜索目录。

                  希望对您有所帮助。

                  【讨论】:

                    【解决方案11】:

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

                    【讨论】:

                    • 这也是我认为正确的解决方案,但官方installation guide并没有说JAVA_HOME的任何内容
                    【解决方案12】:

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

                    【讨论】:

                    • 这列出了每一个环境变量!很酷,但我需要一种方法来提取那条路径?有什么想法吗?
                    【解决方案13】:

                    System.getProperty("java.home") 不够好?

                    如果它以“jre”结尾,您就会知道那是 jre,您可以尝试查找根文件夹并检查仅 JDK 附带的不同文件以确保。

                    【讨论】:

                    • System.getProperty("java.home") 会给我 JRE
                    • 你不能用那个文件夹作为起点吗?走到父级,然后检查某些文件以查看您使用的 JRE 是 JDK 附带的,还是只是一个简单的 JRE
                    猜你喜欢
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2017-05-19
                    • 2023-03-20
                    相关资源
                    最近更新 更多