Как программно получить все установленные Java JVM (не по умолчанию), используя Java?
Кто-нибудь знает, как программно получить все JVM, установленные (не по умолчанию), используя Java?
Например, на компьютере пользователя установлено 2 JVM:
JDK 5
JDK 6
Мне нужно знать все версии, установленные для того, чтобы переключить ту, которая используется (по умолчанию), и затем программно вызвать javac для компиляции некоторого исходного кода с использованием определенной версии JDK.
Я искал некоторую информацию в Интернете, я нашел:
- Как программно получить версию Java (не по умолчанию)?
- Как мне программно получить путь к jdk / javac?
Но я не мог найти то, что искал.
10 ответов
Я недавно имел дело с очень похожей ситуацией. Следующий код делает почти то, что вам нужно. Он ищет Java JRE и JDK, а не только JDK, но его должно быть довольно легко редактировать в соответствии с вашими потребностями. Осторожно: только для окон
/**
* Java Finder by petrucio@stackru(828681) is licensed under a Creative Commons Attribution 3.0 Unported License.
* Needs WinRegistry.java. Get it at: https://stackru.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@stackru (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));
}
}
}
Вам также понадобится обновленный WinRegistry.java для чтения значений из 32-разрядных и 64-разрядных разделов реестра Windows: /questions/40502991/chtenie-zapis-v-reestr-windows-s-ispolzovaniem-java/40502995#40502995
Я обычно не программист Java, поэтому мой код, вероятно, не соответствует соглашениям Java. Подай в суд на меня.
Вот пример запуска с моей 64-битной машины Win 7:
>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
Я сделал быструю проверку реестра Windows, и этот ключ, кажется, предоставляет различные версии Java, установленные в системе.
HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Runtime Environment
При дальнейшем поиске в Google было подтверждено, что это правильное местоположение. Прочитайте эти статьи для деталей...
Быстро получить доступную Java JVM на рабочей станции (Windows)
На платформах Windows вы можете запросить, существует ли установленная JRE:
java -version:1.6 -version
Эта команда вернется с "Java-версией"1.6.0_xx"", если она у вас установлена. Если он не установлен, он скажет: "Невозможно найти спецификацию совещания JRE 1.6".
Похоже, что это не работает в Linux, потому что у Linux нет стандартного способа установки Java.
В командной строке Windows вы можете запустить следующие 2 команды (или запустить вместе как пакетный файл). Это будет выглядеть в Windows Установка и удаление программ (записи реестра) и сообщит, какие версии JAVA найдены с помощью ссылок установки / удаления, а также пути к папке и некоторых других вещей.
wmic product where "name LIKE '%%java%%'" get * /format:textvaluelist > temp_javavers.txt
notepad.exe temp_javavers.txt
По сути, нет способа перечислить всю JVM, даже не из кода Java. Рассмотрим различные платформы, разных поставщиков JDK, JDK в комплекте с другими продуктами от баз данных до авиасимулятора и движка рендеринга видео. Большинство JDK представляют собой простые ссылки на другие, например, v1.2 указывает на установленную v.6 . Обычное дело - как получить версию: java -version Но у нас есть несколько моментов:
- Для Windows посмотрите реестр HKEY_LOCAL_MACHINE\Software\JavaSoft\ . Также рассмотрим режим Wow6432Node для 64-битной ОС. Проверьте продукты от основных поставщиков, которые создают программное обеспечение на Java.
- Mac OS X / System/Library/Frameworks/JavaVM.framework/Versions + Open JDK
- Linux и некоторые другие Unix - какие java, /etc/alternatives/java rpm -qa|grep java и т. Д.
Установлено довольно расплывчато - даже если JRE и JDK поставляются с установщиком, на самом деле нам просто нужно скопировать файлы JRE или JDK на компьютер и сразу же использовать их.
В общем, вам нужно найти все java
или же java.exe
исполняемые файлы на вашем локальном компьютере и вызов java -version
чтобы увидеть1, если этот исполняемый файл с именем java
/ java.exe
на самом деле (часть) JRE.
Только что увидел, что вы запросили JVM и хотите вызвать компилятор. Если вы ищете JDK, используйте вышеуказанный метод, но найдите все javac
/javac.exe
, У них есть -version
вариант тоже.
1 нет никакого риска - нет веселья, которое приходит с этим методом - пожалуйста, внимательно посмотрите на комментарий Шона! Если вы не можете доверять машине (или ее пользователям), то вы можете проверить, является ли исполняемый файл скриптом / пакетом или двоичным файлом - даже если двоичный файл может стереть и ваш диск, даже оригинальный исполняемый файл javac может быть заменен каким-то злобным кодом...
Я не уверен, что это ответит на ваш вопрос, но вы можете контролировать, какую основную версию JRE будет запускать апплет или приложение WebStart, используя функцию Family Versioning. Это позволяет вам указать основной выпуск Java, на котором работает апплет. Вы должны быть в состоянии определить местоположение javac
оттуда.
http://www.oracle.com/technetwork/java/javase/family-clsid-140615.html
Чтобы найти версии Java, лучший подход, чем поиск javac.exe, - проверить реестр. Java создает раздел реестра HKEY_LOCAL_MACHINE\Software\JavaSoft\Java Runtime Environment
со строкой CurrentVersion
установите номер версии, например, 1.5 или 1.6.
Вы можете использовать эту информацию, чтобы найти 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
Вы можете увидеть больше здесь: http://java.sun.com/j2se/1.4.2/runtime_win32.html
Я не знаком с доступом к реестру из Java, но вы всегда можете запустить интерфейс командной строки regedit и проанализировать результаты, что я и сделал.
..компилировать некоторый исходный код, используя определенную версию JDK.
Используйте JavaCompiler (в последней версии JDK, которую пользователь может заложить) с соответствующими опциями для -source
, -target
&-bootclasspath
, Последние два являются частью параметров кросс-компиляции javac
,
Как найти JDK, поп JFileChooser
с путем текущего JRE в качестве каталога по умолчанию. Если пользователь не может перейти оттуда к JDK, сомнительно, что он должен писать код.
Как было сказано ранее, HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Runtime Environment
должен перечислить доступные JVM, НО я только что узнал, что, хотя этот реестр в настоящее время перечисляет только 64-битную 1.6.0_31 JVM на моей машине, у меня также есть 32-битная Java, установленная под C:\Windows\SysWOW64
,
Таким образом, информация, указанная в реестре, не отображает полную картину, и если вы хотите запустить 32-битную JVM в 64-битной Windows, вам также следует попробовать C:\Windows\SysWOW64
,