TL;DR -- Different shells store environment variables in different locations. Set environment variables using your shell's recommended location.
There are plenty of resources out there for installing Java on Ubuntu, but I wanted to write one that covers the exact issue I ran into when installing Java with
This post focuses on the process for installing Java with
zsh as compared to installing Java with
bash. If you've no interest in
zsh and just want to know how to bang it out with
bash, I suggest reading this Digital Ocean post instead.
Update Package Manager
Before doing anything, it's a good idea to update our package manager:
sudo apt update sudo apt upgrade
With that out of the way, the first thing I like to do is clear out any existing Java installations before making any other changes.
Check the existing Java installation
We can start by seeing what our existing Java setup looks like by issuing a command:
# WSL java -version # press enter # output openjdk version "17.0.5" 2022-10-18 OpenJDK Runtime Environment (build 17.0.5+8-Ubuntu-2ubuntu122.04) OpenJDK 64-Bit Server VM (build 17.0.5+8-Ubuntu-2ubuntu122.04, mixed mode, sharing)
Remove existing Java installation
You may or may not want to remove an existing Java installation. I prefer to start fresh, just in case.
In the previous step, I saw that I had the OpenJDK packages installed for Java, so I proceed with removing them.
commentsadd context (actions such as tab completions, saving files, re-opening the terminal)
# WSL sudo apt remove --autoremove openjdk- # press tab repeteadly # installed packages should be listed with tab completion # after pressing tab, it autocompletes to: sudo apt remove --autoremove openjdk-17-jre-headless:amd64 # press enter # if more than one package appeared in the previous step, make sure to remove all of them # source the shell (or close and re-open your terminal application) source ~/.zshrc # confirm Java is no longer installed java -version # press enter # output zsh: command not found: java
Install desired Java version
Now we can install the appropriate version of Java (more specifically, the JDK). In my case, it's version
So, we can just add
openjdk- in the command below (replace
17 with whatever version you need to install):
sudo apt install openjdk-17 # press tab to see packages listed # output openjdk-17-dbg openjdk-17-jdk openjdk-17-jre-headless openjdk-17-demo openjdk-17-jdk-headless openjdk-17-jre-zero openjdk-17-doc openjdk-17-jre openjdk-17-source # we want a headless JDK, we so end up with: sudo apt install openjdk-17-jdk-headless # source the shell or restart the terminal source ~/.zshrc # confirm Java installation java -version # press enter # output openjdk version "17.0.7" 2023-04-18 OpenJDK Runtime Environment (build 17.0.7+7-Ubuntu-0ubuntu122.04.2) OpenJDK 64-Bit Server VM (build 17.0.7+7-Ubuntu-0ubuntu122.04.2, mixed mode, sharing)
$JAVA_HOME environment variable
We're not quite done yet, though. We need to set the
$JAVA_HOME environment variable.
I'll first describe the way I initially tried it so that I can illustrate how much more straightforward the correct way is.
The wrong way
This is where I got thrown off by
zsh. I didn't realize that
zsh handles environment variables differently than
I made the mistake of adding
JAVA_HOME to my
/etc/environment file (the
bash way). The result went something like this:
# /etc/environment JAVA_HOME="/path/to/java/home" # save and exit /etc/environment # source the file source /etc/environment echo $JAVA_HOME # outputs /path/to/java/home, yay! # close terminal # open new terminal echo $JAVA_HOME # no output, uhh.. wtf?
At this point, I thought I would get clever and source
/etc/environment within my
It almost worked:
# .zshrc source /etc/environment # save and exit .zshrc # close and re-open terminal echo $JAVA_HOME # success!
So far so good, but when I try to open a project with VS Code from the terminal...
code . # presss enter zsh: command not found: code
I decide to get clever once again, and add my entire
$PATH variable to my
# /etc/environment PATH="/home/this/path:/home/that/path:/another/path:/vs/code/path" JAVA_HOME="/java/home/path"
This solution actually worked, but it felt so hacky. I just knew there had to be a better way...
The right way
Before we jump in, note that the configuration has been reset from the previous section, (titledThe wrong way):
source /etc/environmentremoved from
JAVA_HOMEvariable deleted from
the terminal was session closed and re-opened
Now we can go about setting
echo $JAVA_HOME # press enter # no output # find the Java install path sudo update-alternatives --config java # press enter # output There is only one alternative in link group java (providing /usr/bin/java): /usr/lib/jvm/java-17-openjdk-amd64/bin/java Nothing to configure.
From here we can copy the path that was output:
The place you put that path will depend on a few factors:
which shell you're using
whether this Java configuration is being set at the profile level or the system level
Luckily, what we put in the file is the same, regardless of scope or shell:
# at the bottom of the appropriate file from the table above JAVA_HOME="/usr/lib/jvm/java-17-openjdk-amd64/bin/java"
Save and exit the file, then close and re-open the terminal.
Now we can see that
JAVA_HOME is set if we echo it out:
echo $JAVA_HOME # output /usr/lib/jvm/java-17-openjdk-amd64/bin/java
That's it! Your Java configuration is ready to go, and your shell commands remain intact.