This is part of a larger series on installing and maintaining Java. To view the previous post, click here.
Maintaining Java on MacOS is a bit complicated. Apple preinstalls a Java Development Kit package, and maintains it through it’s integrated update process. This means that you’ll have the latest version of the Oracle JDK. Unfortunately Apple doesn’t provide a simple way to downgrade or keep previous versions. But, we’ll provide instructions here.
== Oracle JDK
This video covers the instructions laid out in the rest of the article.
Feel free to follow along, listen and read, or simply follow the written instructions with screenshots.
Applying all updates from Apple will ensure you have the latest Oracle JDK. This can be done through the Apple Appstore, which is be found in your Applications folder on your Dock.
MacOS Applications Folder Location Screenshot
Then open your Appstore.
Appstore Location Screenshot
In the Appstore, click Updates in the top menu.
Appstore Updates Location Screenshot
If you see any updates for MacOS, install them. The details for each update should explain what is included. You can also see a history of previous patches. Since I’ve been a good boy, you can see I have no pending patches.
Appstore Updates Screen Screenshot
But what if you need an earlier version? Or even an unreleased version? Well, Oracle has an archive of all Java runtimes for all supported OSes.
Oracle Jave Runtime Archive Screenshot
Simply click the version you need, and this will take you to a page to download an installer specific to your OS. Make sure to accept the license agreement with the radio button at the top of the list of downloads.
Available Java 7 Downloads Screenshot
For MacOS you’ll get a DMG file.
MacOS JDK DMG File Screenshot
Simply double click it to mount, and MacOS should automatically open the disc image and show you a Finder window with a PKG file.
MacOS JDK DMG Contents Screenshot
If you’re not familiar, PKG files are modifications to MacOS. Installing Java does require some changes to the system. Simply double-click the PKG file to run the installer. Click the Continue button.
Oracle JDK MacOS Installer 01 Screenshot
This will take you to an information screen telling how much space the Oracle JDK will use. Click the Install button.
Oracle JDK MacOS Installer 02 Screenshot
The installer makes system level changes. Because of this, MacOS will prompt you for your admin password. Enter your password to allow the installation to continue. This is your last opportunity to cancel with no changes being made.
Oracle JDK MacOS Installer 03 Screenshot
The installer will copy all the files you need to use the Oracle JDK. It should not take long. 2 or 3 minutes at most. You should see a progress bar as shown.
Oracle JDK MacOS Installer 04 Screenshot
When the installer completes, click Cancel to exit.
Oracle JDK MacOS Installer 05 Screenshot
With the instaler complete, you’d think MacOS would use the newly installed version by default, however, that is not the case. If you open your window and enter:
MacOS terminal showing default Java version
We could still select the newly installed version in many applications. Both the Eclipse and IntelliJ IDEs allow you to select a different installed Jaa version in your project settings. However, what if we want other applications to use the new version? We need to use an additional command to make MacOS start using the new version by default. MacOS provides a lot of supporting scripts to help us. One of these is a script to output the path to an installed version for Java. In your terminal type this command:
MacOS Terminal Default Java Home Output
If you’d like to see what versions are installed, you can list the contents of the JavaVirtualMachines path from the previous output.
ls -la /Library/Java/JavaVirtualMachines
MacOS Terminal List of Installed Java Versions
What we need is a way to tell all Java applications which installed version we want them to use. Apple and Oracle used to give us a special control panel in the System Preferences to control this. But that was abandoned in 10.8.2 in favor of the standard in the Java community of storing the path to the installation in a system environment variable JAVA_HOME. So we need to set this environment variable for our system.
Fortunately, since MacOS X is based on FreeBSD, and since FreeBSD is very similar to Linux, we can reuse Linux methods to set this. There are effectively two ways to set an environment variable for use system wide. I’m assuming you’re using the default command line shell BASH. If you’ve changed to another shell, you probably already know enough that you don’t need this guide.
BASH uses two files to configure you shell for you. The .bash_profile and the .bashrc files stored in the user’s home directory. On MacOS the two configurations effectively serve the same purpose, but there is a distinct difference we should consider so we know what we’re setting. The .bash_profile is used to configure your shell before you actually login. This means that anything set in the .bash_profile will be set for anyone who logs in, or any application that runs under your permissions.
Except as root. Root is always special. Root also comes with its own .bash_profile and .bashrc. So everything we’re covering here still applies. Just keep in mind that you need to set the configuration for the user that will use the setting.
Now, the .bashrc is effectively the same. But the .bashrc is used after you login. So I think a little breakdown of the order of operations will help.
1. *Normal System Boot*
2. *Root .bash_profile*
3. *User's .bash_profile*
4. *User logs via interactive session*
This includes manual login or submission of a key like SSH
5. User’s .bashrc
At least, that’s the normal order of operations. The odd thing about MacOS is that is completes a login for you from when you first login as part of it’s start-up. Thus, while on Linux, we would need to care about this distinction. On MacOS, the entire process is completed when we first boot the system and complete the first login. I still find it’s a good practice to follow the more universal standard even if it’s not relevant to a specific situation. You build good habits. You ensure you learn why you follow certain steps by actually understanding what is happening, and you make your work more portable, which means you can more easily reuse your work.
TL;DR is, open your .bash_profile and make the change there. This might be a bit of a challenge because MacOS doesn’t show hidden files in Finder by default. All files that begin with a “.” are treated as hidden files. It’s an old Unix convention. We’ll have a post later about common OS modifications developers use to make life easier. For now, unless you like to use a terminal editor, simply use this command in your terminal to open your .bash_profile in Text Edit:
Open /Applications/TextEdit.app ~/.bash_profile
This command will open your default text editor. Since I use Atom, that is what’s shown here.
bash_profile in Atom
Mine is a customized. You will add the below line anywhere in the file. You should add the comment in the example so you’ll remember for later. Make sure to read the line as the comment has information you will need. Yes, I’m hiding it there to make you read it. Read it.
# Setting the environment variable to set the default JDK.
export JAVA_HOME=export JAVA_HOME=`/usr/libexec/java_home -v 1.7`
The -v argument sets the version you want to use. If you’re happy with the default version, you don’t even need this line. You can also drop the -v argument.
With that set. Open your terminal and check the version reported by Java. You can find that command earlier in this article. With that, you’ve installed your desired version of Java and set it as the default for all applications. Be mindful that some applications may behave weirdly. Especially if they come with their own wrappers to execute them. Don’t be too surprised if you find some odd game, or custom tool that overrides this setting for their own use.
These cases should be very rare as this is very bad behavior for a developer. All Java developers should respect the JAVA_HOME environment variable. At best, if needed, the developer should either package their own JRE with their application, or offer their own start option to set the JRE independent of the system JRE.