Find absolute java.exe path programmatically from java code
Asked Answered
C

6

28

If I have a java jar or class file which is launched by the user (assuming java path is set in environment variables), so how can i from within the code, figure out absolute path of java.exe/javaw.exe from which this file is being launched.

Like on ubuntu we can run: % which java and it shows the path.

However on windows, if i check System.getenv() it may happen that there are multiple path's found e.g for old or new version. If through cmd line, I run java -version it does not show the path.

Can you tell me either through pure java or command line on windows how is it possible to find out the location of javaw.exe?

Calumnious answered 25/1, 2012 at 16:21 Comment(2)
Why do you need the location of the exe? Might you want to get the location of the jar instead?Charqui
@Thomas, i need both. Location of jar can be found easily. I need to install my application as a windows service, and for that i need the abs path of default javaw.exe Actually it is there in Path but i am confused as it can show multiple entries of old and new versions, wondering how would i now which one is the default one?Calumnious
L
38
String javaHome = System.getProperty("java.home");

Can you tell me either through pure Java ... on windows how is it possible to find out the location of javaw.exe?

E.G.

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

Output

C:\Program Files (x86)\Java\jdk1.6.0_29\jre\bin\javaw.exe    exists: true
Press any key to continue . . .

And yes, I am confident that will work in a JRE.

Laryngitis answered 25/1, 2012 at 16:30 Comment(7)
Thank you, actually on my machine if i check Path=C:/Program Files/Java/jre7/bin; while JAVA_HOME=C:\Program Files\Java\jdk1.6.0_26 So i am just wondering for system without jdk, would JAVA_HOME still be set with JRE Path?Calumnious
Actually to test it i would have to uninstall jdk, but if you could confirm then i will have my answer, thank youCalumnious
But the JAVA_HOME is not necessarily the java.exe that is used to launch the currently running application. I have three different JDKs installed and only a single JAVA_HOME.Leathern
@a_horse_with_no_name, yes you are right but Andrew's answer is what i was looking for. I was trying System.getenv("JAVA_HOME") while what i needed was: System.getProperty("java.home");Calumnious
appears you can also programmatically tell whether you're running java vs. javaw or not, see #14632772Studley
For future readers, the direction layout of JDK8 and JDK11 are different. However, this answer works reliable on both directory layouts. It is also useful to find keytool(.exe)Cw
On JRE this returns: java.home:C:\Program Files\Java\Temurin_jre8_1.8.0_322 but on JDK this will point the JRE inside JDK: java.home:C:\Program Files\Java\jdk8u362-b09\jreIgnazio
I
5

On Windows, the java.library.path System Property begins with the path to the bin directory containing whichever java.exe was used to run your jar file.

This makes sense, because on Windows the first place any executable looks for DLL files is the directory containing the executable itself. So naturally, when the JVM runs, the first place it looks for DLLs is the directory containing java.exe.

You can acquire the path to java.exe as follows:

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";

This code is Windows-specific - I hard-coded the path separator (;) and the file separator (). I also put in a fallback to just "java" in case the library path trick somehow doesn't work.

I have tested this with Java 6 and 7 on Windows 7. I tried a 32-bit and 64-bit version of Java.

Indiscriminate answered 10/2, 2015 at 19:10 Comment(1)
If you use the constructor with parent and child parameters, then you don't have to worry about the backslash: new File(javaLibraryPath.substring(0, javaLibraryPath.indexOf(';')), "java.exe")Haunch
S
2

Here's a slightly more generalised solution that I came up with. Maybe useful:

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;
    }
}
Stolon answered 20/10, 2017 at 15:26 Comment(0)
C
1

Compilation of All above methods

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 "";
    }
Cacogenics answered 19/6, 2022 at 20:26 Comment(0)
M
1

If you are running on Java 9+ you can use following snippet to check the Java command:

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

This will use the new Java Process API to get the handle of itself. From there you can parse the path as needed.

Source

Maharani answered 15/6, 2023 at 16:56 Comment(0)
L
0

an issue with using "System.getProperty("java.home");", is that it is not always the java exe that the jar is running on, if you want to get that, you can use "System.getProperty("sun.boot.library.path");", from there you can find "java", "java.exe", "javaw", or "javaw.exe"... However there is still an issue with this, java will run just fine if the executable has been renamed, and the actual java executable's structure changes from different JRE's/JDKS's, so there is not much way to find the java exe if it has been renamed. unless someone else has a method ofc, in which case, can you share? :)

(Also, I have seen some people suggest using the first index of System.getProperty("java.library.path");, note, this might not work if the user/launcher has manually set the library path, something which is not too uncommon)

Lang answered 9/5, 2022 at 0:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.