What is JAVA_HOME? How does the JVM find the javac path stored in JAVA_HOME?
JVM does not find java.exe
. It doesn't even call it. java.exe
is called by the operating system (Windows in this case).
JAVA_HOME
is just a convention, usually used by Tomcat, other Java EE app servers and build tools such as Gradle
to find where Java lives.
The important thing from your point of view is that the Java /bin
directory be on your PATH
so Windows can find the .exe
tools that ship with the JDK: javac.exe
, java.exe
, jar.exe
, etc.
Difference between java.home and JAVA_HOME
As you stated, JAVA_HOME points to the JDK installation path given by the Environment Variable(%JAVA_HOME%).
But java.home points to the JRE installation path, now it returns the JRE that was used to run the application, please remember that you can have multiple versions of JRE and JDK on the same server/computer
And you can run an application specifying what jre or jdk you want to use.
So, for example, if you have on your Environment path:
%JAVA_HOME% = C:\Program Files\Java\jdk1.6.0_24
But if you ran the application using an specific jre:
"C:\Program Files (x86)\Java\jre1.8.0_73\bin\java" -jar TheJavaFile.jar
Inside the application on run-time, you will get on java.home a different version of the JAVA_HOME
This may explain why on some cases you get different versions for both variable and system property.
Also, please notice that the paths may be quite different, since JRE is a different product than JDK, then they are installed in different locations, because they are independent
Now, regarding what's the difference from one JDK vs JRE, this diagram explains it pretty clear:
JDK is a superset of JRE, and contains everything that is in JRE, plus
tools such as the compilers and debuggers necessary for developing
applets and applications. JRE provides the libraries, the Java Virtual
Machine (JVM), and other components to run applets and applications
written in the Java programming language.
How do I find where JDK is installed on my windows machine?
If you are using Linux/Unix/Mac OS X:
Try this:
$ which java
Should output the exact location.
After that, you can set JAVA_HOME
environment variable yourself.
In my computer (Mac OS X - Snow Leopard):
$ which java
/usr/bin/java
$ ls -l /usr/bin/java
lrwxr-xr-x 1 root wheel 74 Nov 7 07:59 /usr/bin/java -> /System/Library/Frameworks/JavaVM.framework/Versions/Current/Commands/java
If you are using Windows:
c:\> for %i in (java.exe) do @echo. %~$PATH:i
Should JAVA_HOME point to JDK or JRE?
If you're doing any sort of development, or building with Maven or Ant, you need to point to the JDK (Java Development Kit) where utilities such as javac
(the Java Compiler) reside. Otherwise, you can point to the JRE (Java Runtime Environment).
The JDK contains everything the JRE has and more. If you're just executing Java programs, you can point to either the JRE or the JDK.
JAVA_HOME should point to a JDK not a JRE
Control Panel -> System and Security -> System -> Advanced system settings -> Advanced -> Environment Variables -> New System Variable
Finding JDK path and storing it as a string in Java
You may be able to find the JDK path by looking to see where javac is installed.
Assuming that "javac" is within the environment paths of the system then you can retrieve the path by passing "where javac" to code such as the following
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;
}
The string returned will be the exact location of javac so you may need extra processing to get the directory that javac resides in. You will need to distinguish between Windows and other OS
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
Note: if the method returns null / error it doesn't mean that javac doesn't exist - it will most likely be that javac isn't within the PATH environment variable on windows and so cannot be found using this method. This isn't likely on Unix as Unix usually adds the jdk/bin directory to the PATH automatically.
Also, this will return the javac version currently in use at command line, not necessarily the latest version installed. so if e.g. 7u12 and 7u13 are installed but command prompt is set to use 7u12 then that's the path that will be returned.
Only tested on multiple Windows machines but works fine on them.
Hope this is helpful.
Related Topics
When to Use an Assertion and When to Use an Exception
Creating an Animated 4X4 Grid in Java
Which Part of Throwing an Exception Is Expensive
Why Does This Gridbaglayout Not Appear as Planned
How to Do Query Auto-Completion/Suggestions in Lucene
Eclipse Will Not Open Due to Environment Variables
Mapping List in Yaml to List of Objects in Spring Boot
Do/Can Abstract Classes Replace Interfaces
How to Set Java Max Heap Size for Running from a Jar File
Are There Any Java Method Ordering Conventions
Installing Java on Os X 10.9 (Mavericks)
Why Shouldn't Java Enum Literals Be Able to Have Generic Type Parameters
How to Remove Element from Arraylist by Checking Its Value