1. brew install openjdk@<version>
2. ln -s <homebrew path> </Library/JavaVirtualMachines/>
3. /libexec/java_home -v <version>
Afaik, with some aliases in you *shrc it basically reimplements sdkman, what else does it give you?
OK but what benefit does that give? I hope we're not back to the bad old days of different apps needing different brands of JDK to run on.
But even if you don't have that, most people work on at most a handful of apps at a time, and again I would defer checking against a specific version to CI most of the time rather than switching around which JVM I'm using locally, unless your code was very tightly coupled to JVM internals somehow.
sdk use java xxx
And done. A new LTS is released? Just sdk install it. Set the one you use most as default, and focus on the project instead of managing JDKs.Oh, and very occasionally you'll actually get hit by a bug within one Java major version (like when they removed historic offsets from the timezone database included in the JVM, that was fun). At that point being able to switch between minor versions easily is quite nice.
But can you not just install 24 on your dev box and use that to work on either branch, maybe with -source/-target arguments? It never used to be a problem to develop with a newer JVM even if it was an older project.
Even if you do all developing on the latest LTS, you will want to be able to switch to whatever version is running on the dev or prod application servers to replicate a bug as closely as possible.
By the way, you are ignoring the case I mentioned where a JDK bug happened between one minor version and the next.
Occasionally, sure. But is it really frequent enough to worry about?
> By the way, you are ignoring the case I mentioned where a JDK bug happened between one minor version and the next.
I am, because I don't see why it's a case you'd worry about. Just install the version without the bug.
I mean sure, I can see some minor advantages to making it easy to change JDK versions. But for how often you want to do that, it really doesn't seem worth the overhead of having another moving part in your setup.
Sometimes the JDK version you are targetting cannot be changed at that time, for a variety of reasons, most beyond your control.
Sometimes the JDK contains or triggers a bug you need to workaround and test in various minor versions.
Sometimes you need to switch to the exact minor version used in production.
Often you need to switch JDKs even within a single project, more often with several projects.
In the years that I've used SDKMan the number of times I invoked it to switch JDK versions in a terminal was more than once on hundreds of days (along with hundreds of days where whatever I set it to was fine for weeks on end). All painless, quick, and easy. Why wouldn't anyone involved in developing Java in a corporate setting make life easier on themselves? Those are not 'minor advantages', those are major time and mental overhead savers. It's a trivial tool to install and maintain too with almost no overhead for me to worry about. And if it breaks? Then the last version I configured will just keep working, and I can spend maybe half an hour to set up an alternative. That hasn't happened yet, so for a tool I've been using for a decade or so, that's pretty good.
If you're running x.0.3 in production, you'd run x.0.3 locally. If there's a JVM bug that your application hits on x.0.3, either it's a showstopper in which case you'll find a way to upgrade/fix production quickly, or it's something you can tolerate, in which case you can tolerate it in local dev too. If you decide it's time to upgrade to x.0.4, you'd upgrade to x.0.4 locally, test a bit, then upgrade to x.0.4 in production. What's the scenario where you need to keep switching between x.0.3 and x.0.4 locally? You upgraded application Y to x.0.4, then discovered that application Z hits a showstopper bug and needs to stay on x.0.3? That's not a situation that you let fester for months, you either fix or work around the bug pretty quickly, or you decide that x.0.4 is too buggy and put everything back to x.0.3, and for that short period sure theoretically you would want to develop application Y under x.0.4 but the risk of developing it under x.0.3 is pretty damn small.
I get the argument that the cost is pretty low. It's just this is addressing something that really doesn't feel like a problem for me, and something that I don't think should be acceptable for it to be a problem. The JVM always used to be something you could upgrade almost fearlessly, and I think there was a lot of value in that.
Sometimes you still need Java 8 to compile for super old programs — think decades old IoT devices too small to handle newer JVMs that you still need to do the occasional minor update for.
But really sdkman is just nice to be able to quickly install and quickly switch jvms without worrying about any opinions the os package manager may have. If I want an old jre8, do I need to fuss around with finding the right package repo for my arch etc, or should I just use sdkman and be done with it.
1. No version manager, download and install manually. Not that hard, since it's just a zip file and maybe set JAVA_HOME envvar. If you need multiple versions to co-exist, skip this.
2. Use OS' "native" package manager. Brew, apt, chocolatey.
3. Generic package manager like asdf.
4. SDKMAN!, JBang, jEnv, jabba...
Deciding is easy. But remembering which one you used 6 months ago when you want to install another version...
- make (via its tasks feature)
- direnv (via its environments features)
- Just about most package managers (via it's dev tools features)
It has backends for just about anything (aqua, cargo, asdf, gem, github, go, etc).
It allows for locking your tooling similar to a package.json lock file.
And the nice thing is that it does it a lot better those tools (I recently found out make gobbles up any error codes and returns 2).
And sdkman is written in rust and only needs curl, zip and unzip, no JVM.
`mise ls-remote java` to show all vendors and versions, or just `mise latest java@temurin` (or any other vendor) to get the latest version string
`mise use -g java@<version>` to install it and set it as a default
On macOS I wrote my own 9-line Zsh function that lists the JDKs available and sets JAVA_HOME.
In containers you'll never switch at all, just install whatever you want and be done with it.
ETA: I see in another comment someone said this doesn't work for things that aren't OpenJDK. But I've yet to run into a situation where I'd want to install anything except OpenJDK. That said, I think update-java-alternatives would work with them if they provide deb files to install themselves.
Then it's just:
sdk use java 11.0.29-tem
And in that terminal it will use that, while another terminal happily uses a different version. That's useful when you are running two tools on different Java versions which interact. Installing another version is trivial too.I use it when I have projects with different jdks or nodejs.
Then SDKMAN! will perform the switch automatically when you enter the directory.
Does it have any interaction with e.g. Maven Toolchain?
First of all, multiple vendors has always been a thing in Java since the early 2000's.
Second, configuring a couple of environment variables isn't that much of a challenge.
Third, all IDEs have an option to use a bundled JVM, and allow for JVM selection per project.
Finally, for applications the modern way is to build the runtime alongside the application, or AOT compilation.
Early 2000s? There was usually one language version that circulated. We had the blackdown java on debian, whatever version sun hosted (1.3?) and something IBM made which was probably on a password protected ftp site available to corporate clients. And it was like that for years. Now there's like 10 vendors supporting 3-5 different major language versions that change every few months.
We are not talking about what was available only to GNU/Linux folks as free beer.
It’s TCK-certified, supported by Amazon, and completely free.
So I don’t see the need to use any other distribution, unless it is for a niche requirement.
For the remaining 5%, on macOS, my JVM version manager is this zsh one-liner:
jvm () { export JAVA_HOME=`/usr/libexec/java_home -v $1`; }As I understand it, Oracle's JVMs only get free updates for a limited time. If you keep using them after that you risk getting caught in a license audit.
I used asdf for a while but moved to mise-en-place (mise). Same reasons though, one tool manager for all the tools.
On Windows, the only sane way to install Java seems to be scoop.sh or chocolatey
scoop bucket add java
# Install JDK 11
scoop install java/temurin11-jdk
# Install JDK 17
scoop install java/temurin17-jdk
# Use JDK 11
scoop reset temurin11-jdk
# Use JDK 17
scoop reset temurin17-jdk
I also wrote a short guide on my website:
https://raizensoft.com/tutorial/install-java-gamedev/With scoop you can just launch the terminal and run `scoop reset [java-version]`
- Most of the JDKs mentioned are simply builds of openjdk. There are a few exceptions with alternative runtimes from e.g. IBM. But unless you have a good reaon to use those, use any OpenJDK build. They are functionally identical and the certified ones pass an extensive test suite to guarantee that. Coretto is a safe bet with long term support and backported fixes.
- There's a difference between developers and production usage here. Tools like sdk man are for developers that need to switch between specific versions in different projects. You see the same in the python, ruby, js, etc. world. System wide installations aren't that useful. Unlike many of those, project dependencies are never system wide. There's no global installation of Java dependencies.
- Avoid Oracle's builds unless you need them for compliance reasons. Their licensing can get expensive and they are famously pretty aggressive on enforcing terms. There is no functional advantage to using their builds. They aren't faster or better in any way. There is no Oracle specific secret sauce.
- If you are on Linux or mac, getting your sdk via your favorite package manager is fine for casual use. Just be aware that this might not necessarily work with all software projects you want to work on. If that matters to you, that's what sdkman is for.
- JDKs take up a lot of space. A lot of tools are trigger happy to add JDKs but don't necessarily remove them. Tracking down and removing redundant JDKs is something I have to do regularly. Some tools try to be a bit too smart and will ignore the presence of perfectly good jdks I have installed with sdkman (e.g. intellij).
- Use containers for deployment and pick the right base image. You should not need server side jdk installations unless you are doing things the old school way.
Am I just a Java rookie, or would Java benefit from equivalents for Python's ruff/uv/ty?
Obviously, lots of tooling already exists (Python's did too). But distilling all the lore and xml into a handful of fast opinionated cli tools seems useful to me anyway.
All you have to do is link your SDKMan binaries with Jenv and you can easily switch with one command.
Picking a JDK is simple. You pick the latest Temurin LTS. It'll work, and if it doesn't, grab the Zulu with JavaFX already plugged in or suss out the incantation for implanting it into your Temurin through web search.
Besides JDK management SDKMan also provides an easy to understand interface for toolchains for things like Clojure and Kotlin and also stuff such as Quarkus.
lihaoyi•2mo ago
You don't need to globally install Apache-Commons, nor is there a "Apache Commons Version Manager" that you need to first install to then manage your different versions of Apache Commons. So why should the JVM need such a thing? Well with Mill, it doesn't