On June 25, 2020, I tweeted that Coursier was providing a way to make installing Scala and Scala-related tools easier. I’ll look into that more soon, but in this tutorial I’ll show something different: How to install multiple JVMs/JDKs with Coursier.
Note 1: If you only want to see what the Coursier commands look like, skip down to the “cheatsheet” section at the bottom of this article to see the common Coursier/Java commands.
Note 2: I use the terms JDK and JVM interchangeably below. To me you’re actually installing a JDK and then using a JVM when you use the
java command, but other people seem to use the terms interchangeably, so I do as well.
Getting rid of my old JVMs
The first thing I did was to delete all of the JVMs I installed last week with Homebrew. I used these commands to uninstall JDK 11, JDK 14, and jEnv:
brew uninstall openjdk@11 // uninstall jdk 11 brew cask uninstall java // uninstall jdk 14 brew uninstall jenv // uninstall jenv
I also had to remove some jEnv settings from my ~/.bash_profile file.
Next, I visited the Coursier installation page, and installed its
cs command on my MacOS system with this command:
curl -fLo cs https://git.io/coursier-cli-macos && chmod +x cs && (xattr -d com.apple.quarantine cs || true) && ./cs
That creates a
cs file in my current directory, and I moved that to my bin directory, ~/bin.
List installed JDKs
To make sure my system was clean I used this Coursier command to list all installed JVMs:
cs java --installed
That command came back empty. I also tried to run
java -v, and it told me there were no installed JDKs. (On a Mac you can also use the /usr/libexec/java_home command.)
List available JDKs
To list all of the available JDKs — all of the JDKs Coursier knows about — use this command:
cs java --available
That lists 250 available options, so I then ran this command:
cs java --available | grep adopt
That cuts the list down to 48 options. I’m only interested in JDK 11 and JDK 14 right now, and these are the two I want:
Installing a JDK
It turns out that there are at least two ways to install a JDK with Coursier. If you want to be very clear about which one you want to install, use these commands to get the JDK 11 and 14 versions listed above:
cs java --jvm adopt:1.11.0-7 cs java --jvm adopt:1.14.0-1
Or, to get the latest version of each JDK, use these commands:
cs java --jvm 11 cs java --jvm 14
Note that these JDKs are installed in these directories on a MacOS system:
Now when I run the Coursier
installed command, I see this output:
$ cs java --installed adopt:1.11.0-7 adopt:1.14.0-1
Note that if you don’t have any other JDKs installed and just want to install the “default” JDK, you can use this command:
The way this command works is:
- If you don’t have any other JDKs installed, that command installs the default JDK, which is currently Java 1.8.x
- If you do have a JDK installed and set up as shown below, that command runs the JDK’s
As noted, there are many other Java versions available, so look at the output from the
available command to see those versions.
Specifying a JDK to use
Now that the JDKs are on your system, you need a way to declare which one you want to use. At this point if I try to run a
java command on my system I see this output:
$ java No Java runtime present, requesting install.
(Then I see a MacOS dialog appear with a prompt about installing Java.) So I know that the JDKs are on my system, but the system can’t find them.
You can show the
JAVA_HOME environment for each installed JDK with these commands:
$ cs java --jvm 11 --env export JAVA_HOME="/Users/al/Library/Caches/Coursierfirstname.lastname@example.org/Contents/Home" $ cs java --jvm 14 --env export JAVA_HOME="/Users/al/Library/Caches/Coursieremail@example.com/Contents/Home"
To set the
JAVA_HOME variable to use JDK 14, you can now use this command:
$ eval "$(cs java --jvm 14 --env)"
After issuing that command, I see this output when running the
$ java -version openjdk version "14.0.1" 2020-04-14 OpenJDK Runtime Environment AdoptOpenJDK (build 14.0.1+7) OpenJDK 64-Bit Server VM AdoptOpenJDK (build 14.0.1+7, mixed mode, sharing)
Similarly I can switch to JDK 11 with this command:
$ eval "$(cs java --jvm 11 --env)"
Note that on MacOS, this command just changes the
JAVA_HOME environment variable.
Note that you can also list the
JAVA_HOME value with this command:
$ cs java-home /Users/al/Library/Caches/Coursierfirstname.lastname@example.org/Contents/Home
You can also clear the
JAVA_HOME value with this command:
$ eval "$(cs java --disable)"
Uninstalling a JDK
I don’t see any commands to uninstall a JDK. But fortunately that’s pretty easy to do from the command line. On a Mac, just go to this directory, and then delete the JDK(s) you want to delete under that directory:
The Coursier documentation says that these are the “managed JVM directories” for Mac, Linux, and Windows systems:
Linux: ~/.cache/coursier/jvm MacOS: ~/Library/Caches/Coursier/jvm Windows: ?
Note that on a MacOS system, Coursier keeps its previous downloads cached in this directory:
This cache includes files that are downloaded with Coursier via SBT, so if you delete this cache, SBT will need to re-download them when they are needed again.
To get help on what Java-related commands are available, use this Coursier command:
$ cs java --help
There are more things you can do with Coursier, so see the main Coursier Java page for more details.
Here’s a cheatsheet that summarizes the Coursier Java commands that are available:
cs java --help # java-related help cs java --available # list all available jvms cs java --installed # list installed jvms cs java # show the current JDK version # OR install the default jvm (currently 1.8.x) cs java --jvm adopt:1.14.0-1 # install specific jdk 14 version cs java --jvm adopt:1.11.0-7 # install specific jdk 11 version cs java --jvm 11 # install the latest jdk 11 (email@example.com) cs java --jvm 14 # install jdk 14 (firstname.lastname@example.org) cs java-home # show current JAVA_HOME (such as ~/Library/Caches/Coursieremail@example.com/Contents/Home) # show JAVA_HOME for JVM 11 $ cs java --jvm 11 --env export JAVA_HOME="/Users/al/Library/Caches/Coursierfirstname.lastname@example.org/Contents/Home" # show JAVA_HOME for JVM 14 $ cs java --jvm 14 --env export JAVA_HOME="/Users/al/Library/Caches/Coursieremail@example.com/Contents/Home" # set JAVA_HOME to JDK 14 $ eval "$(cs java --jvm 14 --env)" # JVMs are installed here: /Users/al/Library/Caches/Coursier/jvm # Previous downloads are kept here: /Users/al/Library/Caches/Coursier/v1
Summary: Coursier Pros & Cons
Coursier is an interesting command-line tool. Once you know the commands, and where things are installed, it’s a fast way to use multiple JVMs. The pros and cons I’ve seen so far are:
- Works on Mac, Linux, and Windows
- It’s plenty fast
- It lets you install and use multiple JVMs (many different ones)
- You can use similar commands to install Scala and Scala tools
- Everything goes in just a few spots, so if you want to manually delete things you can
- It’s used by other tools like SBT and Ammonite
- It has many other commands that I’ve barely looked at yet
- The commands to switch JVMs are not simple and easy to remember, but this can be remedied with some aliases and/or shell scripts
- I didn’t see any commands to delete/uninstall JVMs, but you can do that manually
- I don’t know how updates work yet, i.e., how it works when there’s a new version of Java 11 or 14 in my examples
I just took another look at the jEnv docs, and I didn’t think about this earlier, but it looks like you should be able to use jEnv with the Coursier JDK installations. I found that jEnv made it easy to switch JDKs from the command line, and the Coursier commands are a little hard to remember, so I may try that.
Other possible solutions: Homebrew, jEnv, and SDKMAN
As I mentioned at the beginning of this article, I was using Homebrew and jEnv to manage multiple JDKs, and my takeaway there was that Homebrew is a little slow, but jEnv was easy to use.
I haven’t used SDKMAN, so I can’t compare the experience of using it. But I have its docs, and it looks like a terrific tool as well.