Skip to content

Instantly share code, notes, and snippets.

@gwpantazes
Last active November 13, 2024 09:42
Show Gist options
  • Save gwpantazes/50810d5635fc2e053ad117b39b597a14 to your computer and use it in GitHub Desktop.
Save gwpantazes/50810d5635fc2e053ad117b39b597a14 to your computer and use it in GitHub Desktop.
How to install different JDK versions on MacOS with Homebrew

How To Install Different JDK Versions on MacOS with Homebrew

Keywords: Java, JDK (Java Development Kit), MacOS, Homebrew, Specific Version

This how-to guide covers how to install different versions of the JDK on MacOS with Homebrew.

Table of Contents

Preface

This Guide Favors OpenJDK

This guide favors OpenJDK.

This guide favors free, simple, and permissive licensing whenever possible, so we will favor OpenJDK first, then AdoptOpenJDK if plain OpenJDK isn't available, any other open source distributions, and finally Oracle JDK if no other options are available. We favor OpenJDK because it has a permissive license, the GPL v2 with Classpath Exception (aka linking exception). For more information, see Oracle now requires a subscription to use Java SE (2018).

  • For Java 8 and later, OpenJDK is readily available.
  • For versions prior to Java 8 or other special circumstances, OpenJDK may not be available. We will cover how to install whatever is most readily available.

About Command Line Outputs

Note that this guide contains plenty of CLI command outputs. The intent of including these outputs is to illustrate what output should look like. Our goal IS NOT to keep up with exactly what the output is at the present day. This guide DOES NOT guarantee or even attempt to keep all those command outputs updated with the ever-evolving Hombrew formulae changes.

What's important are the commands, and the general form of the outputs. This guide WILL attempt to keep up-to-date with the best commands to run.

Just be aware that if something's been working for a while, the command output might look old, but the command itself will probably still run fine for more recent updates.

Introduction Homebrew

Hombrew Setup

Install Homebrew.

Remember to frequently brew update. Homebrew may also auto-update upon running key homebrew commands such as install or upgrade.

$ brew update
Updating Homebrew...
==> Auto-updated Homebrew!
Updated 1 tap (homebrew/cask).
==> Updated Casks
foo

Double check your registered taps by running brew tap. It's generally good practice to have homebrew/cask and homebrew/cask-versions taprooms tapped, especially when installing multiple Java versions.

Check your taps.

$ brew tap
homebrew/cask
homebrew/cask-versions
homebrew/core
homebrew/services

If homebrew/cask and homebrew/cask-versions aren't in the list of your registered taps, then run brew tap homebrew/cask and brew tap homebrew/cask-versions to tap them.

Tap into the cask caskroom.

$ brew tap homebrew/cask
==> Tapping homebrew/cask
Cloning into '/usr/local/Homebrew/Library/Taps/homebrew/homebrew-cask'...
remote: Enumerating objects: 72, done.
remote: Counting objects: 100% (72/72), done.
remote: Compressing objects: 100% (58/58), done.
remote: Total 491774 (delta 34), reused 29 (delta 14), pack-reused 491702
Receiving objects: 100% (491774/491774), 226.08 MiB | 25.32 MiB/s, done.
Resolving deltas: 100% (348965/348965), done.
Tapped 1 command and 3713 casks (3,831 files, 242MB).

Tap into the cask-versions caskroom.

$ brew tap homebrew/cask-versions
==> Tapping homebrew/cask-versions
Cloning into '/usr/local/Homebrew/Library/Taps/homebrew/homebrew-cask-versions'...
remote: Enumerating objects: 34, done.
remote: Counting objects: 100% (34/34), done.
remote: Compressing objects: 100% (28/28), done.
remote: Total 230190 (delta 17), reused 6 (delta 6), pack-reused 230156
Receiving objects: 100% (230190/230190), 59.24 MiB | 7.37 MiB/s, done.
Resolving deltas: 100% (158472/158472), done.
Tapped 166 casks (213 files, 65.6MB).

Getting an Overview: How to Search Homebrew for Java formulae

A lot of the information in this how-to guide is simply gathered from brew search and brew info. If you're still getting the hang of things, I highly recommend you run these commands yourself to get an overview of what's available and learn how to search Homebrew's formulae.

Java/JDK formula/cask names typically contain either java or jdk. Let's brew search for java and jdk to see potential formulas.

$ brew search java
==> Formulae
app-engine-java            java11 ✔                   jslint4java
google-java-format         javacc                     libreadline-java
java ✔                     javarepl                   pdftk-java
==> Casks
charles-applejava   eclipse-javascript  java6               netbeans-java-se
eclipse-java        java-beta           netbeans-java-ee    oracle-jdk-javadoc

If you meant "java" specifically:
It was migrated from homebrew/cask to homebrew/core.

We can see some of the formulae/casks we're looking for, such as java, java11, or java-beta.

$ brew search jdk
==> Formulae
openjdk ✔                  openjdk@11 ✔               openjdk@8 ✔
==> Casks
adoptopenjdk               jdk-mission-control        oracle-jdk-javadoc
adoptopenjdk8              oracle-jdk                 sapmachine-jdk

We can see some more potential formulae/casks we're looking for, such as openjdk, adoptopenjdk8, and oracle-jdk.

Get the summary and metadata for a formula/cask you are interested in by running brew info <formula> or brew cask info <cask>.

As an example, let's start simple and get the info of java. java is an alias for the openjdk formula. At the time of writing, the current version is OpenJDK 15.

$ brew info java
Warning: Treating java as a formula.
openjdk: stable 15.0.1 (bottled) [keg-only]
Development kit for the Java programming language
https://openjdk.java.net/
/usr/local/Cellar/openjdk/15.0.1 (614 files, 323.8MB)
  Poured from bottle on 2020-11-05 at 14:06:55
From: https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/openjdk.rb
License: Cannot Represent
==> Dependencies
Build: autoconf ✔
==> Caveats
For the system Java wrappers to find this JDK, symlink it with
  sudo ln -sfn /usr/local/opt/openjdk/libexec/openjdk.jdk /Library/Java/JavaVirtualMachines/openjdk.jdk

openjdk is keg-only, which means it was not symlinked into /usr/local,
because it shadows the macOS `java` wrapper.

If you need to have openjdk first in your PATH run:
  echo 'export PATH="/usr/local/opt/openjdk/bin:$PATH"' >> ~/.zshrc

For compilers to find openjdk you may need to set:
  export CPPFLAGS="-I/usr/local/opt/openjdk/include"

==> Analytics
install: 181,357 (30 days), 434,315 (90 days), 1,183,511 (365 days)
install-on-request: 71,666 (30 days), 175,260 (90 days), 260,903 (365 days)
build-error: 0 (30 days)

Installing Java

Early Access (EA) OpenJDK Feature Release

The java-beta cask contains the OpenJDK Early Access JDK.

Double check information about the cask, such as JDK build version and OpenJDK.

$ brew cask info java-beta
java-beta: 16,25
https://jdk.java.net/
/usr/local/Caskroom/java-beta/16,25 (144B)
From: https://github.com/Homebrew/homebrew-cask-versions/blob/HEAD/Casks/java-beta.rb
==> Name
OpenJDK Early Access Java Development Kit
==> Description
Early access development kit for the Java programming language
==> Artifacts
jdk-16.jdk -> /Library/Java/JavaVirtualMachines/openjdk-16.jdk (Generic Artifact)

Install the early access feature release of the OpenJDK.

$ brew cask install java-beta
==> Downloading https://download.java.net/java/early_access/jdk16/25/GPL/openjdk
Already downloaded: /Users/georgep/Library/Caches/Homebrew/downloads/ce9292709109d07c9bd145508e429bcb4a446bf13f2e6828e66a253b3ad8cb71--openjdk-16-ea 25_osx-x64_bin.tar.gz
==> Verifying SHA-256 checksum for Cask 'java-beta'.
==> Installing Cask java-beta
==> Moving Generic Artifact 'jdk-16.jdk' to '/Library/Java/JavaVirtualMachines/openjdk-16.jdk'
🍺  java-beta was successfully installed!

Latest Stable Generally Available (GA) OpenJDK Feature Release (Java 15, 16, etc...)

  • The openjdk is a formula avilable on homebrew/core. You don't have to tap any additional taprooms/caskrooms.
  • There is a java alias which points to openjdk, if you prefer the alias.

Double check information about the formula, such as JDK version and OpenJDK being the source.

$ brew info openjdk
openjdk: stable 15.0.1 (bottled) [keg-only]
Development kit for the Java programming language
https://openjdk.java.net/
/usr/local/Cellar/openjdk/15.0.1 (614 files, 323.8MB)
  Poured from bottle on 2020-11-05 at 14:06:55
From: https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/openjdk.rb
License: Cannot Represent
==> Dependencies
Build: autoconf ✔
==> Caveats
For the system Java wrappers to find this JDK, symlink it with
  sudo ln -sfn /usr/local/opt/openjdk/libexec/openjdk.jdk /Library/Java/JavaVirtualMachines/openjdk.jdk

openjdk is keg-only, which means it was not symlinked into /usr/local,
because it shadows the macOS `java` wrapper.

If you need to have openjdk first in your PATH run:
  echo 'export PATH="/usr/local/opt/openjdk/bin:$PATH"' >> ~/.zshrc

For compilers to find openjdk you may need to set:
  export CPPFLAGS="-I/usr/local/opt/openjdk/include"

==> Analytics
install: 181,357 (30 days), 434,315 (90 days), 1,183,511 (365 days)
install-on-request: 71,666 (30 days), 175,260 (90 days), 260,903 (365 days)
build-error: 0 (30 days)

Install the most recent stable feature release of OpenJDK

$ brew install openjdk

NOTE: Pay attention to the caveat about manually symlinking the jdk into /Library/Java/JavaVirtualMachines. It's a manual "opt-in" to treating the Java installation as recognizable by the system at large. It's recommended you run the provided symlink command.

OpenJDK 11

JDK 11 is an LTS (Long Term Support) version.

  • There is no such thing as a java-lts formula or cask, because there is no single LTS version. You must explicitly choose to install Java 11.
  • Note that this formula is available on homebrew/core, so you don't need to have tapped any caskrooms.
  • There is a java11 alias which points to openjdk@11.
$ brew info openjdk@11    # Confirm information about the formula. Note that it's poured from the OpenJDK formula.
$ brew install openjdk@11 # Install OpenJDK 11

Older OpenJDK Feature Release (Java 9, 10, 12, 13, 14, etc.)

Homebrew does not offer an obvious way to install an older feature release of Java other than the current generally-available feature release. For example, there is no such formula as openjdk@14 or java14 in homebrew/core, nor is there such a cask in homebrew/cask or homebrew-cask-versions.

There is good reason for this; out-of-date feature releases are explicitly not supported by OpenJDK. Only the current feature release is supported (thus we get formulae with continual version updates like openjdk). Quoting jdk.java.net - JDK 14 Releases:

JDK 14 has been superseded. Please visit jdk.java.net for the current version.

Older releases, which do not include the most up to date security vulnerability fixes and are no longer recommended for use in production, remain available in the OpenJDK Archive.

If you still need to install an Older JDK Feature Release, here are some recommendations.

  • Manually download and install your desired version from the OpenJDK Archive.

  • Use SDKMAN to install either OpenJDK or AdoptOpenJDK versions. See SDKMAN for more info.

    ~ sdk list java
    ================================================================================
    Available Java Versions
    ================================================================================
    Vendor        | Use | Version      | Dist    | Status     | Identifier
    --------------------------------------------------------------------------------
    AdoptOpenJDK  |     | 15.0.1.j9    | adpt    |            | 15.0.1.j9-adpt
                  |     | 15.0.1.hs    | adpt    |            | 15.0.1.hs-adpt
                  |     | 14.0.2.j9    | adpt    |            | 14.0.2.j9-adpt
                  |     | 14.0.2.hs    | adpt    |            | 14.0.2.hs-adpt
                  |     | 13.0.2.j9    | adpt    |            | 13.0.2.j9-adpt
                  |     | 13.0.2.hs    | adpt    |            | 13.0.2.hs-adpt
                  |     | 12.0.2.j9    | adpt    |            | 12.0.2.j9-adpt
                  |     | 12.0.2.hs    | adpt    |            | 12.0.2.hs-adpt
                  |     | 11.0.9.j9    | adpt    |            | 11.0.9.j9-adpt
                  |     | 11.0.9.hs    | adpt    |            | 11.0.9.hs-adpt
                  |     | 8.0.275.j9   | adpt    |            | 8.0.275.j9-adpt
                  |     | 8.0.275.hs   | adpt    |            | 8.0.275.hs-adpt
                  |     | 8.0.272.hs   | adpt    |            | 8.0.272.hs-adpt
    ...
    Java.net      |     | 16.ea.24     | open    |            | 16.ea.24-open
                  |     | 16.ea.7.lm   | open    |            | 16.ea.7.lm-open
                  |     | 16.ea.2.pma  | open    |            | 16.ea.2.pma-open
                  |     | 15.0.1       | open    |            | 15.0.1-open
                  |     | 14.0.2       | open    |            | 14.0.2-open
                  |     | 14.0.1       | open    | local only | 14.0.1-open
                  |     | 13.0.2       | open    |            | 13.0.2-open
                  |     | 12.0.2       | open    |            | 12.0.2-open
                  | >>> | 11.0.2       | open    | installed  | 11.0.2-open
                  |     | 10.0.2       | open    |            | 10.0.2-open
                  |     | 9.0.4        | open    |            | 9.0.4-open
    ...

Java 8

Brew has an openjdk@8 formula.

$ brew info openjdk@8
$ brew install openjdk@8

Another option is installing AdoptOpenJDK 8 via cask.

$ brew tap homebrew/cask-versions   # cask-versions must be tapped to get access to this caskto different cask versions.
$ brew search jdk                   # Find `adoptopenjdk8` in the casks
$ brew cask info adoptopenjdk8      # Confirm information about the cask. Note that this is an AdoptOpenJDK build of OpenJDK.
$ brew cask install adoptopenjdk8   # Install the AdoptOpenJDK build of OpenJDK8

See the AdoptOpenJDK HomeBrew Tap Github Repo for an alternative taproom with more AdoptOpenJDK versions.

Java 7

  • 💀OBSOLETE💀: It appears Java 7 is no longer available in homebrew/cask-versions. It used to be available at caskroom/versions/java7.
# THIS IS OBSOLETE. INCLUDED FOR REFERENCE PURPOSES.
$ brew cask info caskroom/versions/java7 # Query info about Java cask installation beforehand
$ brew cask install caskroom/versions/java7 # For Java 7

If you know how to find Java 7 on Homebrew, please leave a comment on how to do so and we can add it in here. 😜

Java 6

  • Note from the metadata in brew info java6 that this is JDK is for Apple OSX.
$ brew info java6
java6: 1.6.0_65-b14-468
https://support.apple.com/kb/DL1572
Not installed
From: https://github.com/Homebrew/homebrew-cask-versions/blob/HEAD/Casks/java6.rb
==> Name
Apple Java 6 Standard Edition Development Kit
==> Description
Legacy runtime for the Java programming language
==> Artifacts
JavaForOSX/JavaForOSX.pkg/Payload/Library/Java/JavaVirtualMachines/1.6.0.jdk -> /Library/Java/JavaVirtualMachines/1.6.0.jdk (Generic Artifact)
$ brew tap homebrew/cask-versions # Make sure you have cask-versions tapped
$ brew cask info java6            # Double check information about the cask.
$ brew cask install java6         # Install Java6 for OSX

Notes

  • The MacOS Java install location is /Library/Java/JavaVirtualMachines/.
    • Certain formulae, such as openjdk, do not automatically install into the actual /Library/Java/JavaVirtualMachines/. Instead, the formula will suggest to you in the installation/info caveats to symlink it into that location.
  • When upgrading Java installations with Homebrew
    • Be aware upgrades will overwrite the cacerts truststore file (if you have edited that).
    • Be aware that the JDK install directory's name may fall out of date when you perform the upgrade. You may have to manually rename the directory, and make tweaks to your configurations accordingly.
  • I recommend jEnv for switching between multiple Java environments on MacOS.
  • I think it's generally wise to have homebrew/cask and homebrew/cask-versions tapped. They are practically core.
  • SDKMAN is a SDK downloader and manager that can be a viable alternative to Homebrew for installing JDKs and even managing them.
@hardik-dadhich
Copy link

Hi @dedoussis ,

$ brew cask info adoptopenjdk8
adoptopenjdk8: 8,252:b09
https://adoptopenjdk.net/
Not installed
From: https://github.com/caskroom/homebrew-versions/blob/master/Casks/adoptopenjdk8.rb
==> Name
AdoptOpenJDK 8
==> Artifacts
OpenJDK8U-jdk_x64_mac_hotspot_8u252b09.pkg (Pkg)

but still how to download minor version 1.8.0_192

@gwpantazes
Copy link
Author

gwpantazes commented Jun 2, 2020

@fazlizekiqi Homebrew's java points to the most recent stable OpenJDK (not Oracle!), so it will probably update to Java 14 in September 2020.

Oracle releases JDK feature release updates first, and typically OpenJDK takes 6 months to catch up and release the same JDK under the OpenJDK organization/license. Refer to Java Version History on Wikipedia to get an overview of this pattern: you can see in the release history table that Oracle's Java SE 14 was released in March 2020, but OpenJDK's release of the same JDK 14 will be ready 6 months later in September 2020. We must take into account these months of lag for OpenJDK to catch up, and we can expect to see Homebrew's java refer to JDK 14 around September 2020 whenever OpenJDK puts up JDK 14. Until then, Homebrew's java will refer to 13.


@dedoussis I have fixed this typo. Thanks for pointing it out.

brew caskinfo adoptopenjdk8 should be corrected to brew cask info adoptopenjdk8


To @jiamo and @hardik-dadhich, while I am not sure why you want older versions of Java, I will still look into how to get and work with multiple specific Java versions and try to see if I can help you with this.

  • Just note that you should probably be using the most recent minor version of whatever JDK you are using unless you are specifically choosing to debug for the older JDK. If you don't have a good reason to be targeting the older JDK, you should update to the newest minor version to get the latest bug and security fixes.
    • OpenJDK's archive warning says it rather clearly, so I will quote them:

      WARNING: These older versions of the JDK are provided to help developers debug issues in older systems. They are not updated with the latest security patches and are not recommended for use in production.

  • My initial guess as to the method you will want to use to get particular older JDKs
    • Getting the Specific JDKs: You will not use Homebrew to get these particular/older JDK versions, but rather download the particular SDK versions straight from OpenJDK's archive, or more likely Oracle's Java Archive since I think you may be referring to a particular Oracle minor version. For example, Java SE JDK 1.8.0_40 and 1.8.0_192 can be found in Java SE 8 Archive Downloads (JDK 8u202 and earlier).
      • Note that Oracle JDK builds require licensing to use in production! I would once again urge that you use OpenJDK, and also upgrade to the most recent minor/patch versions. Doing these two things will avoid both licensing issues and bugs/security problems in older versions. But, I do trust that you have specific reason to need these older versions, so my warning is more for the other folks who might see this conversation. I don't want them to think they need older JDKs for any reason but targeting for specific debugging against that JDK.
    • Managing the Multiple JDKs: Now that you've downloaded the particular Java SDK, I recommend using jenv (Java Environment command line tool) to switch between which JDK is active. It's a very useful tool, please look into its usage on the jEnv site. Just install all the JDK's you want, side by side (they can all be installed at the same time and not replace each other), and jenv will allow you to switch between the active JDK.

I hope this is helpful in the meantime, before I figure out where to put this information either in this document or in another document. If you find a good way to handle this, even if it's not perfect, or if my suggestion in this comment worked for your needs, please comment here. We can iteratively improve the document based on what you find.

@jiamo
Copy link

jiamo commented Jun 3, 2020

@gwpantazes It is helpful. I can download and install by hand.

@hardik-dadhich
Copy link

yes, Such a nice explanation @gwpantazes. Thank you!

@k-funk
Copy link

k-funk commented Nov 12, 2020

Now that 15 is out, can 14 be explicitly installed? Java 15 unfortunately seems to break my build.

@k-funk
Copy link

k-funk commented Nov 12, 2020

To answer my own question: brew tap adoptopenjdk/openjdk && brew install adoptopenjdk14

@gwpantazes
Copy link
Author

@k-funk It's a different tool than Homebrew, but you might want to look into SDKMAN for installing specific versions of Java such as 14 in a similar CLI style. https://sdkman.io

For Homebrew, it looks like it'll be easy to install the popular versions of Java. I think it's a recent update that openjdk is now a core formula which also has @11 and @8 versions, making it very easy to have 8, 11, and the most recent feature release.

For any other versions of Java, maybe the better tool for the job would be SDKMAN.

Note that Homebrew also has java-beta and java6 in cask-versions caskroom, in case anybody needs those.

I may have to update the gist now since it's been a while and things have updated... And possibly include the good use cases for when SDKMAN can shine, and how it could compliment Homebrew.

@gwpantazes
Copy link
Author

asdf is a nice all-purpose tooling version manager that I've been trying out recently. It has a Java plugin which handles downloading/installing and local/shell/global environment (i.e. the roles of Homebrew and jenv respectively). It also has a standard interface for all other languages it supports (which are many: python, ruby, nodejs, etc.), so it's a nice cohesive experience overall. I recommend trying out asdf if you need to do tool version management and switch between multiple versions of things.

@akirna
Copy link

akirna commented Jun 5, 2021

50th ⭐️. Do I get an award? Jk, you deserve an award for writing this. Thanks @gwpantazes.

@mendickxiao
Copy link

brew cask install java6 is failed, cannot find cask.
We can use "brew install --cask java6"

@jlgridley
Copy link

If you need to have openjdk first in your PATH run:
echo 'export PATH="/usr/local/opt/openjdk/bin:$PATH"' >> ~/.zshrc

/usr/local/opt/ doesn't appear to exist on Monterey.

@mm4nn
Copy link

mm4nn commented Apr 28, 2022

@gwpantazes is it possible to install the javadocs for the older java versions? I tried brew search-ing for them with no success :(

@cabb
Copy link

cabb commented Dec 29, 2022

Regarding Java7
You can use the zulu7. Zulu is a certified build of OpenJDK produced by Azul Systems that should be around for a long time.

brew install --cask homebrew/cask-versions/zulu7

@gwpantazes
Copy link
Author

If you need to have openjdk first in your PATH run:
echo 'export PATH="/usr/local/opt/openjdk/bin:$PATH"' >> ~/.zshrc

/usr/local/opt/ doesn't appear to exist on Monterey.

@jlgridley Not sure why /usr/local/opt doesn't exist for you - I"m also on Monterey and I do have /usr/local/opt. If there's any news about the correct different location, please let us know.

@soulflyer
Copy link

/usr/local/opt/ doesn't appear to exist on Monterey.

@jlgridley Not sure why /usr/local/opt doesn't exist for you - I"m also on Monterey and I do have /usr/local/opt. If there's any news about the correct different location, please let us know.

On arm Macs brew uses /opt/homebrew/opt instead of /usr/local/opt. Maybe that is the reason for the different location.

@clintonmedbery
Copy link

Looks like adopt is left behind, I used:
brew install --cask temurin8

@Kamal2301
Copy link

Thank you @gwpantazes 👍🏻

@tinu1976ch
Copy link

If you need to have openjdk first in your PATH run:
echo 'export PATH="/usr/local/opt/openjdk/bin:$PATH"' >> ~/.zshrc

/usr/local/opt/ doesn't appear to exist on Monterey.

@jlgridley Not sure why /usr/local/opt doesn't exist for you - I"m also on Monterey and I do have /usr/local/opt. If there's any news about the correct different location, please let us know.

i use monterey 12.7 and do NOT have /usr/local/opt too
i found my java in the following location:
/Library/Java/JavaVirtualMachines/temurin-8.jdk/Contents/Home/bin
and this path was found in my PATH

hope, this information helps....

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment