5

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

4

13 回答 13

8

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

希望这会有所帮助。

于 2013-04-05T17:54:54.343 回答
2

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

于 2013-03-31T02:39:41.783 回答
2

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

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

C:\Program Files\Java\jdk1.7.0在 windows 和/usr/java/jdk1.7.0_13unix 系统上打印。如果未设置环境属性JAVA_HOME,则返回 null。您应该认为这意味着 java 尚未正确安装/配置,因此您的应用程序无法运行。

于 2013-04-10T16:14:35.487 回答
2

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

于 2013-04-10T20:23:12.013 回答
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));
 }
于 2013-04-11T12:15:22.070 回答
0

System.getProperty("java.home") 对你来说不够好?

如果它以“jre”结尾,您就会知道那是 jre,您可以尝试步行并找到根文件夹并检查仅与 JDK 一起提供的不同文件以确定。

于 2013-03-31T02:10:04.253 回答
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));
        }
于 2013-03-31T02:10:47.600 回答
0

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

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

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

希望有帮助。

于 2013-03-31T14:38:27.073 回答
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转换为 ​​aFile并将一个文件夹返回到 JDK 目录。

于 2013-04-07T05:01:26.930 回答
0

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

于 2013-04-08T09:07:34.493 回答
0

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

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

这不是一个完整的解决方案,而是如何做到这一点的指南。

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

帮助获取进程 ID 的路径如何在 Unix/Linux 中获取进程的路径

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

于 2013-04-10T11:05:06.243 回答
0

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

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

完整的描述在这里

于 2013-04-10T11:33:55.630 回答
0

After thinking about the answer of @Nicolas Rinaudo, I started to write something that just checks any path in the System's properties. I tested this on Windows 10 and Linux (Debian 9) and it pretty much works.

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;
    }
于 2021-01-03T16:03:57.217 回答