如何使用 Java 以编程方式安装所有 Java JVM(非默认安装)?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6493856/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to programatically get all Java JVM installed (Not default one) using Java?
提问by Florencia
Does anyone know how to programatically get all JVMs installed (not the default one) using Java?
有谁知道如何使用 Java以编程方式安装所有 JVM(不是默认的)?
For example, there are 2 JVMs installed on a user's machine:
例如,在用户的机器上安装了 2 个 JVM:
JDK 5
JDK 6
I need to know all the versions installed in order to switch the one that it is on use (by default) and then call javac programatically to compile some source code using a specific JDK version.
我需要知道安装的所有版本,以便切换它正在使用的版本(默认情况下),然后以编程方式调用 javac 以使用特定的 JDK 版本编译一些源代码。
I've been looking for some info on the web, I found:
我一直在网上寻找一些信息,我发现:
- How to programatically get a Java version (Not default one) ?
- How do I programatically get the path to the jdk / javac?
But I couldn't find what I was looking for.
但是我找不到我要找的东西。
回答by Petrucio
I've recently dealed with a very similar situation. The following code does almost exactly what you need. It searches for java JREs and JDKs, not only JDKs, but should be pretty easy to edit to your needs. Beware: windows-only
我最近处理了一个非常相似的情况。以下代码几乎完全符合您的需要。它搜索 Java JRE 和 JDK,不仅是 JDK,而且应该很容易根据您的需要进行编辑。当心:仅限 Windows
/**
* Java Finder by petrucio@stackoverflow(828681) is licensed under a Creative Commons Attribution 3.0 Unported License.
* Needs WinRegistry.java. Get it at: https://stackoverflow.com/questions/62289/read-write-to-windows-registry-using-java
*
* JavaFinder - Windows-specific classes to search for all installed versions of java on this system
* Author: petrucio@stackoverflow (828681)
*****************************************************************************/
import java.util.*;
import java.io.*;
/**
* Helper class to fetch the stdout and stderr outputs from started Runtime execs
* Modified from http://www.javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html?page=4
*****************************************************************************/
class RuntimeStreamer extends Thread {
InputStream is;
String lines;
RuntimeStreamer(InputStream is) {
this.is = is;
this.lines = "";
}
public String contents() {
return this.lines;
}
public void run() {
try {
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line = null;
while ( (line = br.readLine()) != null) {
this.lines += line + "\n";
}
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
/**
* Execute a command and wait for it to finish
* @return The resulting stdout and stderr outputs concatenated
****************************************************************************/
public static String execute(String[] cmdArray) {
try {
Runtime runtime = Runtime.getRuntime();
Process proc = runtime.exec(cmdArray);
RuntimeStreamer outputStreamer = new RuntimeStreamer(proc.getInputStream());
RuntimeStreamer errorStreamer = new RuntimeStreamer(proc.getErrorStream());
outputStreamer.start();
errorStreamer.start();
proc.waitFor();
return outputStreamer.contents() + errorStreamer.contents();
} catch (Throwable t) {
t.printStackTrace();
}
return null;
}
public static String execute(String cmd) {
String[] cmdArray = { cmd };
return RuntimeStreamer.execute(cmdArray);
}
}
/**
* Helper struct to hold information about one installed java version
****************************************************************************/
class JavaInfo {
public String path; //! Full path to java.exe executable file
public String version; //! Version string. "Unkown" if the java process returned non-standard version string
public boolean is64bits; //! true for 64-bit javas, false for 32
/**
* Calls 'javaPath -version' and parses the results
* @param javaPath: path to a java.exe executable
****************************************************************************/
public JavaInfo(String javaPath) {
String versionInfo = RuntimeStreamer.execute( new String[] { javaPath, "-version" } );
String[] tokens = versionInfo.split("\"");
if (tokens.length < 2) this.version = "Unkown";
else this.version = tokens[1];
this.is64bits = versionInfo.toUpperCase().contains("64-BIT");
this.path = javaPath;
}
/**
* @return Human-readable contents of this JavaInfo instance
****************************************************************************/
public String toString() {
return this.path + ":\n Version: " + this.version + "\n Bitness: " + (this.is64bits ? "64-bits" : "32-bits");
}
}
/**
* Windows-specific java versions finder
*****************************************************************************/
public class JavaFinder {
/**
* @return: A list of javaExec paths found under this registry key (rooted at HKEY_LOCAL_MACHINE)
* @param wow64 0 for standard registry access (32-bits for 32-bit app, 64-bits for 64-bits app)
* or WinRegistry.KEY_WOW64_32KEY to force access to 32-bit registry view,
* or WinRegistry.KEY_WOW64_64KEY to force access to 64-bit registry view
* @param previous: Insert all entries from this list at the beggining of the results
*************************************************************************/
private static List<String> searchRegistry(String key, int wow64, List<String> previous) {
List<String> result = previous;
try {
List<String> entries = WinRegistry.readStringSubKeys(WinRegistry.HKEY_LOCAL_MACHINE, key, wow64);
for (int i = 0; entries != null && i < entries.size(); i++) {
String val = WinRegistry.readString(WinRegistry.HKEY_LOCAL_MACHINE, key + "\" + entries.get(i), "JavaHome", wow64);
if (!result.contains(val + "\bin\java.exe")) {
result.add(val + "\bin\java.exe");
}
}
} catch (Throwable t) {
t.printStackTrace();
}
return result;
}
/**
* @return: A list of JavaInfo with informations about all javas installed on this machine
* Searches and returns results in this order:
* HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Runtime Environment (32-bits view)
* HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Runtime Environment (64-bits view)
* HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Development Kit (32-bits view)
* HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Development Kit (64-bits view)
* WINDIR\system32
* WINDIR\SysWOW64
****************************************************************************/
public static List<JavaInfo> findJavas() {
List<String> javaExecs = new ArrayList<String>();
javaExecs = JavaFinder.searchRegistry("SOFTWARE\JavaSoft\Java Runtime Environment", WinRegistry.KEY_WOW64_32KEY, javaExecs);
javaExecs = JavaFinder.searchRegistry("SOFTWARE\JavaSoft\Java Runtime Environment", WinRegistry.KEY_WOW64_64KEY, javaExecs);
javaExecs = JavaFinder.searchRegistry("SOFTWARE\JavaSoft\Java Development Kit", WinRegistry.KEY_WOW64_32KEY, javaExecs);
javaExecs = JavaFinder.searchRegistry("SOFTWARE\JavaSoft\Java Development Kit", WinRegistry.KEY_WOW64_64KEY, javaExecs);
javaExecs.add(System.getenv("WINDIR") + "\system32\java.exe");
javaExecs.add(System.getenv("WINDIR") + "\SysWOW64\java.exe");
List<JavaInfo> result = new ArrayList<JavaInfo>();
for (String javaPath: javaExecs) {
if (!(new File(javaPath).exists())) continue;
result.add(new JavaInfo(javaPath));
}
return result;
}
/**
* @return: The path to a java.exe that has the same bitness as the OS
* (or null if no matching java is found)
****************************************************************************/
public static String getOSBitnessJava() {
String arch = System.getenv("PROCESSOR_ARCHITECTURE");
String wow64Arch = System.getenv("PROCESSOR_ARCHITEW6432");
boolean isOS64 = arch.endsWith("64") || (wow64Arch != null && wow64Arch.endsWith("64"));
List<JavaInfo> javas = JavaFinder.findJavas();
for (int i = 0; i < javas.size(); i++) {
if (javas.get(i).is64bits == isOS64) return javas.get(i).path;
}
return null;
}
/**
* Standalone testing - lists all Javas in the system
****************************************************************************/
public static void main(String [] args) {
List<JavaInfo> javas = JavaFinder.findJavas();
for (int i = 0; i < javas.size(); i++) {
System.out.println("\n" + javas.get(i));
}
}
}
You will also need the updated WinRegistry.java to read values from both the from 32-bits and 64-bits sections of the windows registry: https://stackoverflow.com/a/11854901/828681
您还需要更新的 WinRegistry.java 从 Windows 注册表的 32 位和 64 位部分读取值:https: //stackoverflow.com/a/11854901/828681
I'm not usually a java programmer, so my code probably does not follow java conventions. Sue me.
我通常不是 Java 程序员,所以我的代码可能不遵循 Java 约定。告我。
Here is a sample run from my Win 7 64-bits machine:
这是从我的 Win 7 64 位机器上运行的示例:
>java JavaFinder
C:\Program Files (x86)\Java\jre6\bin\java.exe:
Version: 1.6.0_31
Bitness: 32-bits
C:\Program Files\Java\jre6\bin\java.exe:
Version: 1.6.0_31
Bitness: 64-bits
D:\Dev\Java\jdk1.6.0_31\bin\java.exe:
Version: 1.6.0_31
Bitness: 64-bits
C:\Windows\system32\java.exe:
Version: 1.6.0_31
Bitness: 64-bits
C:\Windows\SysWOW64\java.exe:
Version: 1.6.0_31
Bitness: 32-bits
回答by vikramsjn
I did a quick check of the windows registry, and this key seems to provide the various Java version installed on the system
我快速检查了 Windows 注册表,这个键似乎提供了系统上安装的各种 Java 版本
HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Runtime Environment
HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java 运行时环境
On further google search, it was confirmed that this is the correct location. Read these articles for the details...
在进一步的谷歌搜索中,确认这是正确的位置。阅读这些文章以了解详细信息...
Quickly retrieve available Java JVM on a workstation (Windows)
在工作站 (Windows) 上快速检索可用的 Java JVM
回答by Troy
On Windows platforms, you can shell out to query whether an installed JRE exists:
在 Windows 平台上,您可以 shell 查询是否存在已安装的 JRE:
java -version:1.6 -version
That command will come back with "java version "1.6.0_xx"" if you have it installed. If you don't have it installed, it'll say, "Unable to locate JRE meeting specification 1.6"
如果您安装了该命令,它将返回“java 版本“1.6.0_xx””。如果你没有安装它,它会说,“无法找到符合规范 1.6 的 JRE”
This doesn't seem to work on Linux, probably because Linux has no standard way to install Java.
这似乎不适用于 Linux,可能是因为 Linux 没有安装 Java 的标准方法。
回答by Craig
In Windows Command prompt you could run the following 2 commands (or run together as a batch file). This will look in Windows Add/Remove programs (registry entries) and report which versions of JAVA are found with install/uninstall links, along with folder path, and some other things.
在 Windows 命令提示符下,您可以运行以下 2 个命令(或作为批处理文件一起运行)。这将查看 Windows 添加/删除程序(注册表项)并报告找到哪些版本的 JAVA 带有安装/卸载链接、文件夹路径和其他一些内容。
wmic product where "name LIKE '%%java%%'" get * /format:textvaluelist > temp_javavers.txt
notepad.exe temp_javavers.txt
回答by chro
Basically there is no way to enumerate All JVM even not from Java code. Consider different platforms, diffent JDK vendor, bundled JDK in other products from databases to flight simulator and video rendering engine. Most of JDK are simple link to another, e.g. v.1.2 pointed to installed v.6 . The common thing is how to get a version : java -version But we have some points:
基本上没有办法枚举所有 JVM,即使不是从 Java 代码。考虑不同的平台,不同的 JDK 供应商,将 JDK 捆绑在其他产品中,从数据库到飞行模拟器和视频渲染引擎。大多数 JDK 都是简单的链接到另一个, egv1.2 指向安装的 v.6 。常见的是如何获取版本: java -version 但是我们有几点:
- For Windows look at registry HKEY_LOCAL_MACHINE\Software\JavaSoft\ . Also consider Wow6432Node mode for 64-bit OS. Check products from main vendors whose create software on Java.
- Mac OS X /System/Library/Frameworks/JavaVM.framework/Versions + Open JDK
- Linux and some other Unix - which java, /etc/alternatives/java rpm -qa|grep java , etc.
- 对于 Windows,请查看注册表 HKEY_LOCAL_MACHINE\Software\JavaSoft\。还要考虑用于 64 位操作系统的 Wow6432Node 模式。查看在 Java 上创建软件的主要供应商的产品。
- Mac OS X /System/Library/Frameworks/JavaVM.framework/Versions + Open JDK
- Linux 和其他一些 Unix - 其中 java, /etc/alternatives/java rpm -qa|grep java 等
回答by Andreas Dolk
installedis pretty vague - even if JREs and JDKs are shipped with an installer, in fact we simply need to copy the files of a JRE or JDK to a machine and can useit right away.
安装是相当模糊的——即使 JRE 和 JDK 附带了安装程序,实际上我们只需要将 JRE 或 JDK 的文件复制到机器上就可以立即使用它。
So in general you'd have to findall java
or java.exe
executables on your local machine and call java -version
to see1, if this executable named java
/ java.exe
really is (part of) a JRE.
因此,通常您必须在本地计算机上找到所有java
或java.exe
可执行文件并调用java -version
查看1,如果名为java
/ 的此可执行文件java.exe
确实是(一部分)JRE。
Just saw, that you askedfor JVM and want to callthe compiler.. If you're looking for JDKs, use the above method but find all javac
/javac.exe
. They have a -version
option too.
刚刚看到,您要求JVM 并想调用编译器..如果您正在寻找 JDK,请使用上述方法但找到所有javac
/ javac.exe
。他们也有一个-version
选择。
1there's a no risk - no funthat comes with this method - please have a close look at Sean's comment! If you can't trust the machine(or its users), then you might want to test, if the executable is a script/batch or a binary - even though a binary can wipe your disk too, even the original javac executable can be replaced with some evil-doing-code...
1有一个没有风险-没有什么好玩的附带此方法-请有肖恩的评论仔细看!如果您不能信任机器(或其用户),那么您可能想要测试可执行文件是脚本/批处理还是二进制文件 - 即使二进制文件也可以擦除您的磁盘,即使原始的 javac 可执行文件也可以替换为一些作恶的代码...
回答by maple_shaft
I am not sure if this answers your question, but you can control which major JRE version an applet or WebStart application will run on using the Family Versioning feature. This allows you to specify the major Java release that an applet runs on. You should be able to derive the location of javac
from there.
我不确定这是否能回答您的问题,但您可以使用 Family Versioning 功能控制小程序或 WebStart 应用程序将在哪个主要 JRE 版本上运行。这允许您指定运行小程序的主要 Java 版本。您应该能够javac
从那里得出 的位置。
http://www.oracle.com/technetwork/java/javase/family-clsid-140615.html
http://www.oracle.com/technetwork/java/javase/family-clsid-140615.html
回答by Andrew Thompson
..compile some source code using a specific JDK version.
.. 使用特定的 JDK 版本编译一些源代码。
Use the JavaCompiler(in the latest JDK the user can lay their hands on) with appropriate options for -source
, -target
& -bootclasspath
. The last two are part of the Cross-Compilation Optionsof javac
.
使用JavaCompiler(在最新的JDK中,用户可以使用适当的选项-source
,-target
&-bootclasspath
。最后两个是部分交叉编译选项的javac
。
As to finding the JDK, pop a JFileChooser
with the path of the current JRE as the default directory. If the user cannot navigate from there to a JDK, it is doubtful they should be writing code.
查找JDK,弹出一个JFileChooser
以当前JRE的路径为默认目录。如果用户无法从那里导航到 JDK,那么他们是否应该编写代码是值得怀疑的。
回答by Steven
To find the versions of Java installed, a better approach than looking for javac.exe is to check the registry. Java creates a registry key HKEY_LOCAL_MACHINE\Software\JavaSoft\Java Runtime Environment
with a string CurrentVersion
set to the version number, for example 1.5 or 1.6.
要查找已安装的 Java 版本,比查找 javac.exe 更好的方法是检查注册表。Java 创建一个HKEY_LOCAL_MACHINE\Software\JavaSoft\Java Runtime Environment
带有CurrentVersion
设置为版本号的字符串的注册表项,例如 1.5 或 1.6。
You can use that information to find the JVMs:
您可以使用该信息来查找 JVM:
- HKEY_LOCAL_MACHINE\Software\JavaSoft\Java Runtime Environment\1.5\JavaHome = C:\Program Files\Java\j2re1.5
- HKEY_LOCAL_MACHINE\Software\JavaSoft\Java Runtime Environment\1.5\RuntimeLib = C:\Program Files\Java\j2re1.4.2\bin\client\jvm.dll
- HKEY_LOCAL_MACHINE\Software\JavaSoft\Java Runtime Environment\1.5\JavaHome = C:\Program Files\Java\j2re1.5
- HKEY_LOCAL_MACHINE\Software\JavaSoft\Java Runtime Environment\1.5\RuntimeLib = C:\Program Files\Java\j2re1.4.2\bin\client\jvm.dll
You can see more here: http://java.sun.com/j2se/1.4.2/runtime_win32.html
你可以在这里看到更多:http: //java.sun.com/j2se/1.4.2/runtime_win32.html
I am not familiar with accessing the registry fromJava, but you can always run regedit's command line interface and parse the results, which is what I have done.
我对从Java访问注册表不熟悉,但是您始终可以运行 regedit 的命令行界面并解析结果,这就是我所做的。
回答by Petrucio
As previously said, HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Runtime Environment
should list available JVMs, BUT I just found out that while this registry is currently only listing a 64-bit 1.6.0_31 JVM on my machine, I also have a 32-bit java installed under C:\Windows\SysWOW64
.
如前所述,HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Runtime Environment
应该列出可用的 JVM,但我刚刚发现,虽然这个注册表目前只列出了我机器上的 64 位 1.6.0_31 JVM,但我在C:\Windows\SysWOW64
.
So the information listed on the registry does not paint the full picture, and if you want to run a 32-bit JVM in a 64-bit Windows, you should also try C:\Windows\SysWOW64
.
所以注册表上列出的信息并没有描绘出全貌,如果你想在 64 位 Windows 中运行 32 位 JVM,你也应该尝试C:\Windows\SysWOW64
.