It has been 25 years of Java & Mac OS, both very popular systems but a basic issue like JAVA_HOME path setting still throws occassional errors. I give a step by step understanding here in addition to solution(s) so that users can troubleshoot themselves. Note that no Admin access or SUDO access is needed for this.
Let us understand the PATH variable first. Open your Terminal and type: echo $PATH
The terminal echos the value of the variable named PATH. In unix "$" is used to precede variable names (so echo PATH will just echo the letters PATH). Anyway, what is this $PATH? It is an environment variable that contains a colon-separated list of directories where your shell will look for executables that execute certain terminal commands. This helps because then you dont have to specify the full path to the runtime libraries each time you want to execute something. It makes sense to point out this path only once. This is where PATH entries help. So our goal is to set up a similiar entry for the Java run time so that the terminal shell knows where to look for Java runtime libraries to execute the Java file you want. How do we do that and where is the Java installation on the Mac?
Usually, there is lot of confusion about where the right Java installation is. MacOS thankfully can show us the installation path with a simple command. Just type /usr/libexec/java_home in the Terminal. You will get the installation path. It will be something like "/Library/Java/JavaVirtualMachines/SOME_JDK_VERSION/ Contents/Home". Just copy that path value & do some hardcoding in terminal prompt as follows: export JAVA_HOME=the path you got above
Now you are all set. Actually half-set because the moment you close this terminal session, this value will be reset. The value is not persistent. Also secondly people often frown upon harcodings. Let us fix the second issue first.
Some solutions above suggest to do export JAVA_HOME="/usr/libexec/java_home" or export JAVA_HOME=/usr/libexec/java_home instead of hardcoding the path. The intention is good but it does not work. Instead do this: export JAVA_HOME=$(/usr/libexec/java_home). The $ tells the shell - The value of this expression is the output from executing the command in brackets (i.e. "/us/libexec/java_home"). This fixes the hardcoding issue. Before we go into the other issue (the one of persistence of the PATH value scross sessions), it is imperative to point out one more source of error. Some solutions above suggest to prepend the $HOME variable to the path: export JAVA_HOME=$H0ME/Library/Java/JavaVirtualMachines/YOUR_JDK_VERSION_COMES_HERE/Contents/Home. $HOME is your home directory. You can just try doing echo $HOME in terminal to see what it is. So when we precede the path by $HOME, it is like giving the entire full path. For some reason, this does not work in the OS version I have. Perhapes the OS by default looks under your Home directory & now this smart addition of the extra $HOME causes it to thrown an error. So please avoid this.
Now let us address the persistence issue. In latest Macs, when you open Terminal, the Z-shell zsh opens up. It is the Unix shell that latest MacOS uses & is the default shell program. .zshrc is the configuration file for zsh whenever you open a new terminal window. We can store some configuration stuff there. In fact that is where we will define this JAVA_HOME guy. (Note that we could also store this in the .zprofile file but we will stick to .zshrc). This file's full path is ~/.zshrc. The symbol ~ means the home directory of the logged in user. So you could open the .zshrc file by searching for it in the hard drive of your Mac in your home directory (make sure to enable hidden files to be displayed). Open and manually edit to add an entry for JAVA_HOME. Alternatively, in terminal, we can just do open ~/.zshrc. This opens it up. Manually add the entry:
export JAVA_HOME=$(/usr/libexec/java_home). Make sure there are no blank spaces before or after the "=" sign & also press carriage return (Enter) after the last line. Save. RESTART Terminal (we know why right?). Once you start Terminal, the configuration file runs and sets up everything automatically. Now your Java progrm runs like a charm.
Alternatively, you can hardcode the path in the file by adding: export JAVA_HOME=/Library/Java/JavaVirtualMachines/YOUR_JDK_VERSION_COMES_HERE/Contents/Home. I just gave an indicative path. You need to replace the entire path with the path you got when you typed /usr/libexec/java_home in the Terminal. Don't try prepending with $HOME or other funny business. It is good that you are trying to help by being thorough and providing the complete path but for some reason the (latest) Mac OS (as of Sep 2025) did not appreciate this good intention.
Other issues:
(1) There is no JDK. well, you got to install that first.
(2) There is no .zshrc file. Well, go ahead & create one & add the above line. use the command touch ~/.zshrc to create the file
(3) Multiple versions of Java exist. Use /usr/libexec/java_home -V and select & harcode the path you want. Don't worry about the frowners. Get your system up & running. You can later re-visit this setting when you are more comfortable.
(4) Not the latest Mac OS? Then maybe zsh is not the default editor? Maybe it is bash? Well, no issue cause that one too has a configuration file. Let us look at an interesting way to update that file directly. echo export "JAVA_HOME=\$(/usr/libexec/java_home)" >> ~/.bash_profile. Hey, what is this cool trick? This hack can apply to zsh also. For e.g.:
echo export "JAVA_HOME=$(/usr/libexec/java_home)" >> ~/.zshrc
The >> redirects output of the command preceeding it to the file .zshrc located at ~. It simply appends that output to the end of the file. So this command when executed in Terminal does what we want i.e. set the value of JAVA_HOME in the .zshrc file so that Terminal is able to automatically find the Java runtime libraries. This too works like a charm except that it hardcodes the path directly into the file (which is ok).
Bonus: Now that you have set up the path to Java runtime libraries, you can execute Java files in Terminal. This setting may or may not be read by your IDE. For e.g., I was trying to set up Java in VSCode. Since VSCode is a general IDE you need an "extension" for Java. Microsoft magnanimously has put Oracle's Java extension at the top of the extension search results. So I installed that one by default. It needed me to make an additional setting for JDK path as part of a 1-time configuration set up. There is one more "extension" for Java by Microsoft itself. This one doesent need any config setup and works right off the shelf. Happy coding
brewon an M1 Mac, mine was located/opt/homebrew/Cellar/openjdk/17.0.1_1/libexec/openjdk.jdk/Contents/Home. Obviously change for your version but the typical methods of finding the path proved difficult so I hope this helps others.