Найти абсолютный путь java.exe программно из кода Java
Если у меня есть jav-файл jav или файл класса, который запускается пользователем (при условии, что путь java задан в переменных окружения), то как я могу из кода, определить абсолютный путь к java.exe/javaw.exe, из которого это файл запускается.
Как на Ubuntu мы можем запустить: % which java
и это показывает путь.
Однако на окнах, если я проверю System.getenv()
может случиться так, что найдены несколько путей, например для старой или новой версии. Если через строку cmd, я бегу java -version
это не показывает путь.
Можете ли вы сказать мне через чистый Java или командной строки в Windows, как можно узнать местоположение javaw.exe?
6 ответов
String javaHome = System.getProperty("java.home");
Можете ли вы сказать мне, либо через чистую Java ... в Windows, как можно узнать местоположение javaw.exe?
НАПРИМЕР
import java.io.File;
class JavawLocation {
public static void main(String[] args) {
String javaHome = System.getProperty("java.home");
File f = new File(javaHome);
f = new File(f, "bin");
f = new File(f, "javaw.exe");
System.out.println(f + " exists: " + f.exists());
}
}
Выход
C:\Program Files (x86)\Java\jdk1.6.0_29\jre\bin\javaw.exe exists: true
Press any key to continue . . .
И да, я уверен, что будет работать в JRE.
В Windows системное свойство java.library.path начинается с пути к каталогу bin, содержащему тот файл java.exe, который использовался для запуска файла jar.
Это имеет смысл, поскольку в Windows первое место, где любой исполняемый файл ищет DLL-файлы, - это каталог, содержащий сам исполняемый файл. Поэтому, естественно, когда JVM запускается, первое место, где он ищет DLL, - это каталог, содержащий java.exe.
Вы можете получить путь к java.exe следующим образом:
final String javaLibraryPath = System.getProperty("java.library.path");
final File javaExeFile = new File(
javaLibraryPath.substring(0, javaLibraryPath.indexOf(';')) + "\\java.exe"
);
final String javaExePath =
javaExeFile.exists() ? javaExeFile.getAbsolutePath() : "java";
Этот код специфичен для Windows - я жестко запрограммировал разделитель пути (;) и разделитель файлов (). Я также добавил в качестве отступления просто "java" на случай, если трюк с библиотечным путем как-то не работает.
Я протестировал это с Java 6 и 7 на Windows 7. Я попробовал 32-битную и 64-битную версию Java.
Вот немного более обобщенное решение, которое я придумал. Может быть полезно:
private static String javaExe()
{
final String JAVA_HOME = System.getProperty("java.home");
final File BIN = new File(JAVA_HOME, "bin");
File exe = new File(BIN, "java");
if (!exe.exists())
{
// We might be on Windows, which needs an exe extension
exe = new File(BIN, "java.exe");
}
if (exe.exists())
{
return exe.getAbsolutePath();
}
try
{
// Just try invoking java from the system path; this of course
// assumes "java[.exe]" is /actually/ Java
final String NAKED_JAVA = "java";
new ProcessBuilder(NAKED_JAVA).start();
return NAKED_JAVA;
}
catch (IOException e)
{
return null;
}
}
Компиляция всех вышеперечисленных методов
static String getJavaPath(){
String tmp1 = System.getProperty("java.home") + "\\bin\\java.exe";
String tmp2 = System.getProperty("sun.boot.library.path") + "\\java.exe";
String tmp3 = System.getProperty("java.library.path")+ "\\java.exe";
if(new File(tmp1).exists()) {
return tmp1;
}else if(new File(tmp2).exists()){
return tmp2;
}else if(new File(tmp3).exists()) {
return tmp3;
}else{
String[] paths = System.getenv("PATH").split(";");
for(String path:paths){
if(new File(path + "\\java.exe").exists()){
return path + "\\java.exe";
}
}
}
return "";
}
Если вы используете Java 9+, вы можете использовать следующий фрагмент для проверки команды Java:
import java.io.IOException;
import java.util.Optional;
public class ProcessUtils {
private ProcessUtils() {}
public static Optional getCommandOfCurrentProcess() {
ProcessHandle processHandle = ProcessHandle.current();
return processHandle.info().command();
}
public static void main(String[] args) throws IOException {
System.out.println(ProcessUtils.getCommandOfCurrentProcess());
}
}
Это будет использовать новый API Java Process, чтобы получить дескриптор самого себя. Оттуда вы можете проанализировать путь по мере необходимости.
проблема с использованием
"System.getProperty("java.home");"
, заключается в том, что это не всегда java exe, на котором работает jar, если вы хотите получить это, вы можете использовать
"System.getProperty("sun.boot.library.path");"
, оттуда вы можете найти "java", "java.exe", "javaw" или "javaw.exe"... Однако с этим все еще есть проблема, java будет работать нормально, если исполняемый файл был переименован, и фактическая структура исполняемого файла java изменяется от разных JRE/JDKS, поэтому не так много способов найти java exe, если он был переименован. если у кого-то еще есть метод оф.с, в таком случае не могли бы вы поделиться? :)
(Кроме того, я видел, как некоторые люди предлагают использовать первый индекс
System.getProperty("java.library.path");
, обратите внимание, это может не сработать, если пользователь/программа запуска вручную установили путь к библиотеке, что не так уж редко)