I feel like the actual decision process is fairly straightforward in nearly all cases:
- Use whatever vendor happens to be most convenient to install. If nearly everyone using your OS is installing Java one way, and you're installing it some other unusual way, you should be crystal clear about why exactly you need to do that.
- Generally go with JDK 11, if you may have to deal with older software then maybe go with 8, if you want the shiny new stuff and don't mind some extra hassle then go with JDK 17 (it's not well-supported by everything yet).
That's pretty much it. There are exceedingly few cases where it actually matters whether you installed Corretto or Oracle OpenJDK, and in those cases you'll likely end up either testing all the JDKs anyway to make your decision or writing your own patches for whatever you need.
Presumably this has to do with support and possible testing. People buy RedHat EL for the longterm support, if they use a different vendor for the JDK they have to set up a whole new contract for that with a different company. By contrast, people using a free Linux distro may not have any benefit to using RedHat's JDK.
You will get a l2 sysAdmin or an intermediate developer. If for some reason the root cause is nailed to a reproducible bug then it will go into the bug tracker
That's a good recommendation for library authors, but if you're deploying an application that's regularly maintained, I would recommend using the most recent version -- that's the cheapest, safest way -- and if it isn't, consider an old version (like 11) with one of the LTS offerings, choosing a vendor you trust to support OpenJDK (https://news.ycombinator.com/item?id=28821316).
Of course, new applications should now target 17. It's both the current version and it has LTS.
To me it sounds reasonable that Microsoft tests/optimizes their JDK better for Azure, and Amazon -- for AWS.
Yes -- do what everyone else does.
> Generally go with JDK 11
Seconded.
User rococode is dead on correct here.
If you're using the current JDK version (recommended for regularly maintained applications), it doesn't matter which distribution you choose, as they're all pretty much identical. If you're using an old version (LTS, intended for legacy applications, which might benefit from it), pick a vendor you trust for OpenJDK support, as the builds are not the same, and neither is the support. After Oracle, which contributes about 90% of the work on OpenJDK, the companies distributing builds that contribute to the project and have experience with it are (in rough order of experience and/or contribution): Red Hat, SAP, Azul, Bellsoft, and, more recently, Amazon, and Microsoft.
There are, however, a couple of standouts: Alibaba's Dragonwell, which, last I looked, did not meet the Java specification, and Eclipse Adoptium, built by IBM, which is the only distribution built by a team that isn't involved with the OpenJDK project, isn't very familiar with it, and isn't a member of the OpenJDK Vulnerability team, and so get security patches only after the other vendors have delivered their builds.
Wasn't AdoptOpenJDK the "legit" recommendation a couple years ago? I only heard about all of these other versions sometime later. (Looking again, it looks like the Oracle OpenJDK is shipped in Ubuntu's repos, so maybe I was mistaken).
It was the recommended choice by random internet users who posted blogs, just as is this website, a random website by some random person.
The best way for you to understand which JDK to use is to understand superficially what is involved with the source code and the build process between vendors, and their licenses.
Source code starts out the exact same, that's why they are all OpenJDK, because they take the source code from the OpenJDK public repository's main branch.
From that point on, they can choose to apply source code patches from OpenJDK that have not yet been merged into the main branch, or they could apply their own source code patches. Those patches often will be security fixes, or backported features. Here you have to understand that there is only one main branch of Java. So if you want security fixes or new features but are still on say Java 8, someone has to pull the old commit that was tagged Java 8 and selectively cherry pick a bunch of commits afterwards to apply over it that retrofits all security fixes and possibly a few select new features (like say some performance improvements patches). And if you've ever had to do a cherry pick merge on old code, you know it can be tricky and sometimes there are conflicts and maybe you even need to manually resolve them.
And even if they are not grabbing the source from an older tagged version commit, but are grabbing it from the latest tagged commit (so as of this writing Java 17), well it might already be that there are some newer commits that fixed some security bug, or other bug, or improved performance or startup, etc. So in their build of Java 17 they could even decide to apply some of those patches that happened after to the Java 17 latest release. And they might even choose to apply some patches that haven't even made it to the main branch yet, so maybe still have an open PR, or they are the ones patching something of their own.
After having grabbed the main source of OpenJDK, and potentially applied some patches to it, they proceed to build it for one or more platforms.
In the process of building, they will choose which platform to build for, such as Windows, Linux, MacOS, x64, ARM64, x86, etc. And they will choose what to include in the build, for example should you bundle Java Mission Control, javafxpackager, jarsigner, jstatd, visualvm, etc.
Finally they can choose to tests each build on each platform they built it for by running the full test suites, but they could also only partially test, as in, run only a subset of the tests, or tests only a subset of the platforms they built it for.
You'd want to run tests especially if you did patch the source, to make sure none of your patches introduced bugs, but the build could also have created an issue which tests could uncover, like forgotten to include some important C lib, or resource, or built with wrong optimization options, etc.
And last but not least, the license they choose. There's two parts here, the first one is that if they made any changes to the source of their own, their changes might be on their own license, or might not even be open source. That means you might not be able to fork the exact source they used for your own needs, or even get to see the full source they used. The second are the terms of use for each things bundled in the build. Do they let you use the JRE for cloud applications? Can you redistribute it to others? Can you use it for commercial work, etc.
Hopefully that better equips you to understand. Most of the companies who make money by building OpenJDK and offering support will probably do a good job at making sure that they backport security fixes as soon as possible, and make sure to always test everything to be sure their backport and custom patches didn't break anything, but they might not always do so for your chosen platform. But as any company who wants to make money, they need to have some of their customers pay them at some point, and that's where licensing and terms of use come in, but more and more they go full open source on their source patches and customization, allow anyone to use things for free in all settings, but offer paid support, though to be sure read their license and terms of use.
And if you can't be bothered to read their license or terms of use, that's why people have been recommending AdoptOpenJDK which is now Eclipse Adoptium. Since they're a community effort managed by a non-profit, you can be more confident that their license and terms will be and remain fully open source and free to use in all cases. The downside is that it's a community effort, you don't know if they'll apply security patches quickly, or fully test, etc. And if there's any issue with the build you encounter, there's no real support, no SLA for it, etc.
P.S.: There also exists some alternate JDKs, that are not based from the OpenJDK's main source branch, such as OpenJ9, GraalVM, Zing, JamaicaVM, etc. Those should be considered as alternate implementation of Java, they often have very different runtimes and garbage collector and all that, though they can still partially be using some of the stuff from the OpenJDK as well. While all the OpenJDK builds I was talking before always implement everything using the OpenJDK source, all they'd do is add security fixes, bug fixes, retrofit some newer features into older releases, etc. They wouldn't provide alternate implementation of anything the way that GraalVM or OpenJ9, et all, will do.
Any reasons they are not a member? I would think IBM is trustworthy and mature enough to deal with sensitive security issues.
Unless you want serious long term pain then you shouldn’t be more than one LTS release behind. So if you are not running on JDK 11 or later you should be strongly thinking about upgrading.
My point is that migrating to new releases isn't always trivial, especially the more complicated and complex a project gets. If i knew that i'll run if compiled successfully, then it wouldn't be too bad, but with the amount of reflection, dynamic class loading etc. that frameworks like Spring favor, my workflow to date has been fixing a bug, building and running, something else breaking, fixing that bug, building and running, something else breaking, realizing that i cannot fix this because upgrades to the logic would be inherently "lossy" due to a mismatch of what the new framework versions provide, making it so that breakages that aren't covered by tests will also be created and so on ad infinitum.
Sometimes it makes me wonder why JDK 9 onward just didn't have a compatibility module: "Here, install this to have all of the old Java classes that were removed from the standard library after JDK 8 and retain that old functionality for software projects that would otherwise be stuck in development hell short of a full rewrite." Or something like that for Spring Boot, that lets you use web.xml instead of having to use hacks to load its contents and register all of the servlets, with half of them not working anyways, because some class names were changed along the way.
Software doesn't always age beautifully.
Furthermore, it feels like new runtime and package versions are made in ways that accidentally break backwards compatibility with no clear ways to avoid this.
In some ways, this is just a consequence of a kind of evolutionary leap forward for many applications. We don’t deploy our WARs into application servers anymore, we try to pack a fat JAR, or maybe even a statically linked runtime, into a container. We rebuild the whole world on CI all the time. I mean, Java 8 has issues just respecting cgroup limits, which many a despondent ops engineer has discovered.
I think there’s still room for the 1M SLoC monolith even in this new world, but there are real benefits on the horizon for upgrading to Java 17 and beyond. We’ve reached a point where it’s just more expensive not to make upgrades a regular part of you development cycle. And, no one is stopping you from just staying on 1.8. I mean, I’m sure there are still decaying enterprises stranded on 1.3.
I'm in the middle of a migration to 11 and my general approach has been to get it compiling on 11 while targeting 8 with (--release 8). That seems to catch a great many things that would otherwise fail. The hardest part thus far was figuring out the appropriate libs to replace Java 8 ee stuff, mostly wrt soap and xml. I'm hoping moving to 11 goes smoothly but we'll see. I'm hoping to have the artifacts to a point where they can run on either 8 or 11 without issues.
Mind you; you usually end up with the services all in different states of node/jdk/etc versioning(at least the companies I worked at).
I don't know PrimeFaces, but I have worked with JSP, which does have a flag to set the compiler version (in case you were ever thinking about putting java lambda's in JSP files, which is possible but not recommended due to mixing code).
The hardest part of upgrading the JDK is going from 8 to 9. After 9 it is much more forgivable. As for Spring, major versions are a pain, as is Hibernate. The other parts of Spring are generally well upgradable if you read the Spring changelogs.
They are in there but easy to miss - Bellsoft actually have builds for both jdks and jres for more than mainstream x86_64. Termurin dont even have jres anymore (last time I checked)
Nowadays no one keeps just one JRE in their laptop/desktop and disk sizes are in TBs so no point in saving 100 MB and lacking development tools.
And in one targets containers or systems with small amount of disk jlink give more gains than JRE.
Upgrades now are pretty straightforward if you are past JKD 9 - with JDK 16-17 being a bit tricky, but less than JDK 9.
That depends. If most people follow the advice of "sticking to LTS", these versions will have way more users, and thus will be more "battle-tested", as in tested in production.
Support for vulnerability patches, stability, and so on. You can automatically update and maybe that goes well and maybe problems are caught in testing. Regardless those events and changes have over time have increased costs. LTS should mean lower costs both through increased support focus, increased population of active users, and reduced forced change.
You're not wrong...
In some cases, this may be your ops team.
There haven't been any notable language features added since java 9 besides some basic syntax sugar (which is already covered by stuff like lombok anyway).
For features and performance you might as well just target .NET 6. It has things that have been perpetually 'too hard to implement' (read: oracle doesn't want to pay their engineers to impl it and will sue you if you do it yourself) like value types, generics without type erasure, no checked exceptions, etc. and with .NET 6 performance is better than OpenJDK across the board.
Sometimes you're creating an app that other users need to run in their own environments - and in that case, targeting "latest LTS" is safer, as they may have requirements on what they can run that you don't.
https://projects.eclipse.org/projects/adoptium
> The mission of the Eclipse Adoptium Top-Level Project is to produce high-quality runtimes and associated technology for use within the Java ecosystem. We achieve this through a set of Projects under the Adoptium PMC and a close working partnership with external projects, most notably OpenJDK for providing the Java SE runtime implementation. Our goal is to meet the needs of both the Eclipse community and broader runtime users by providing a comprehensive set of technologies around runtimes for Java applications that operate alongside existing standards, infrastructures, and cloud platforms.
Under Adoption, there is:
* Eclipse Adoption Incubator
* Eclipse AQAvit
* Eclipse Mission Control
* Eclipse Temurin Compliance
* Eclipse Temurin
But yea... the name is awkward.
Why didn't they just keep AdoptOpenJDK? That was a good name IMO.
Eclipse Temurin 17 or Temurin JDK 17 should be sufficient.
A section called "For production use this" or "if you don't know what you're looking for, use this". And "this" can be a particular version (Ubuntu 20.04.6) or a rule of thumb (for production, always use x.y.1 version or above).
Or it can be a table like this one. Django is, as it is in many fields, the gold standard in this regard.
It gets confusing sometimes. Yesterday I was trying to update the python version of one of my applications and was wondering; should I do it now, or do I need to wait for 3.10.1? I did it anyway because the app barely gets traffic anyway, but more clarity is always welcome.
Since then, Oracle completely open-sourced the JDK and the associated tools and gave the the compatibility kits to the community to use. The result is that there are now several different distributions of the JDK. This is undeniably a good thing.
As to the 6-month release cycle, it allows the community to get new features on a much faster cadence than any of the other major languages. If it's too fast for your preferred way of doing things, stick with the LTS releases, which come out on a three-year cycle and include all the features from the prior releases.
There might be reasons not to like Oracle, but their stewardship of Java has been pretty good.
Sun went several years without releasing a new major version, but that same page lists frequent minor updates. So yes, I would call that exactly a stability to treasure.
I think the situation is much better now than it was. The daft renaming of AdoptOpenJDK is the only recent low point.
If there is a bug/performance issue that only happens in the context of AWS, then Corretto would be the most likely to rapidly patch the issue as it impacts their customer base. Potentially patches for those sorts of issues would be discovered by AWS through their own use and testing.
Likewise for the other vendors and their own platforms.
https://docs.gradle.org/current/userguide/compatibility.html
If you switch your Gradle buildscript files over to being written in Kotlin, the problem goes away, as Kotlin's runtime doesn't seem to use any similar explicit checks.
(Doing so also allows you to go further and test out EA JVM builds, e.g. Project Loom, which Groovy-based buildscripts have never been, and will never be, happy with.)
All of this is unnecessarily complicated and confusing, as a developer it really feels like they don't want me to use Java.
I have the feeling that, similarly to what happened with the Roman empire, greed, laziness and burocracy are going to drag everything down.
You have official Oracle JDK build.
You have official Oracle OpenJDK build.
You have plenty of alternative builds.
It's like kernel.org Linux, Debian Linux, Fedora Linux and so on. Does it hurt Linux? I don't think so.
All builds should be perfectly compatible between each other.
Simplest way is just use Oracle JDK 17. It's LTS, free and official.
There's an Oracle jdk whose usage terms need to be deciphered using a lawyer to understand precisely when and how you can use it. So much that the average advice is to not use it. Like if they told you "hey, node.js is cool but don't use the one from those who maintain and develop the code". This would be a huge red flag for any other language than Java, which can leverage 30 years of sunk costs for companies that now will not switch lightly to something else.
The alternative builds are good, yet not official and they might introduce thin incompatibilities or different behaviors. They should not but this whole article suggests that they actually do.
The simple existence of articles like this one testifies that this is a mess for a lot of people.
With SDKMan switching between JDKs is painless, despite the install method of SDKMan itself being one of those.
But it's not just Java. To build our frontend webapp I need NodeJS, and there too some specific version depending on the version of the webapp or just because we've updated.
I'd love to be able to just apt install all of this, but the downsides are just too many.
On the other hand, i only use standard packages through apt/yum/apk/whatever for server software, a distinction that's lost too often in my opinion. Everything that the server needs to operate should have automatic (at least security) updates enabled and ideally the configuration should be fully automated through Ansible with something like GitOps and read only access through SSH (with fallback account with write access for special cases) for maximum auditability and being sure that this is less likely to happen: https://dougseven.com/2014/04/17/knightmare-a-devops-caution...
Furthermore, the servers themselves can be viewed as pretty much disposable at that point. A VM gets corrupted? Wipe it, create a new one, run Ansible against it to set up the environment, then just give the node a label in your container orchestration platform of choice and watch as your business software is automatically provisioned on the node, bringing the total capacity of your cluster up once again.
For personal devices with no important credentials, or development boxes which are similarly unimportant, piping random stuff and trying to work around the problems with multiple SDKs is more permissible, however. Seeing as PHP, Ruby, Go, Java, .NET, Python and other technologies aren't always pleasant to work with if you have different projects that need different environments, as humorously pointed out here: https://xkcd.com/1987/
Containers aren't always comfortable to use for local development (especially with OSes like Windows locally, without WSL2, due to problems with bind mounts but perhaps are for components like DBs, Redis, MongoDB etc.), but in certain dev boxes they are also viable, thus making development even easier.
If anybody's interested:
sudo add-apt-repository ppa:linuxuprising/java
sudo apt-get update
sudo apt-get install oracle-java17-installer oracle-java17-set-defaultYou get mystery bits that haven't been put through the TCK.
Though, I might be missing some important details, and I would love to understand it better.
Edit: a sibling comment suggested that now there's a package repository for that, and indeed there is.
What are some difference between OpenJDK, Adoptium, Azul, BellSoft, etc. besides company dependencies and lifecycle? Which JDK is the fastest, or do certain JDKs perform faster under certain scenarios? Do any of these JDKs have any special features, or can they not do certain advanced reflection (e.g. for efficiency?)
I use IntelliJ so switching JDK is very easy, and most apps work on any JDK. Plus I doubt anything I release would be relevant in the long term (at least without the ability to upgrade JDK). So I really don't have to depend on any JDK, and seems like I don't have to worry about my JDK getting obsolete. Is there still a reason why I would prefer to use one JDK over another?
For example: > Use Corretto, only if you run Java applications directly on Amazon Linux 2 in AWS
Why?
I wonder if c# and mono is better in this respect
As a side note, I appreciate that we have multiple tooling for Java. It doesn't sit well with me when the whole language, and its IDE and compiler and everything is bundled up in one package and that's all you have.
There is definitely a lack "end-to-end" tutorials that don't rely on some form of tooling support. I would love to see more content on how to make a Java program with nothing but an editor and a command line, but I suspect there isn't much of a need for that. Java's tooling is exceptionally good, it's libraries mature and robust. Part of the reason every tutorial out there uses an IDE is because through quirks of history Java is basically an Enterprise programming environment where "Build the Right Thing" predominates over "Worse is Better".
EDIT: There is a REPL included with each JDK after 9 called JShell. It's useful if you just want to get up to speed or if you want to test something quickly.
As for IDEs, I do recommend IntelliJ for writing the code, but in case you want to understand what happens behind the scenes, you can compile the source code directly in the terminal with `javac YourClass.java`, or *.java, depending on how many files you have.
It will by default place the resulting files in the current directory with the convention of creating directories for packages. If you had no package keyword in your files it will result in a simple YourClass.class file that you can run with `java YourClass` (do note that you run classes, not the file itself). If you had something like com.example as a package, it will be placed under WORK_DIR/com/example/YourClass.class.
It should be run from the current work_dir though!
The reason for that is the notion of a class-path, analog of the PATH variable of unix systems. It lists the package-aware class files, and defaults to the working dir, meaning it will find com.example.* files from here, but not elsewhere.
Dependencies are just that, they get concatenated to this class path and thus will be included.
EDIT: You can also just issue `java YourClassWithMain.java`, it will compile and run your class in one go
Java often uses IDE but there are tools to run a REPL. Groovy had this before Java got it. You can use it to write Java, since Java code is Groovy. It comes with a GUI console into which you can type and evaluate too, or you can write script files and run them. It's not as fashionable nowadays as it used to be (now it's Kotlin, Scala, etc.) but it works great and can be useful for learning Java too.
Java is actually nice in that a lot of distros are packaging a version manager for it. Arch and centos lead the pack in this. Although cent continues to be a mess about how many jdks and Jres are available.
BTW. Limited platforms, but covers most of the cases (64 bit linux, windows, mac plus aarch64 for linux and mac)
I've seen, over the past few years, at least a dozen large threads on HN, Reddit, Slashdot, and elsewhere arguing over the JDK.
Usually they're a passionate mix of developers and PMs claiming they're still very confused by the licensing and update / security fix terms since JDK 8, while various Oracle engineers then shout back that the licensing issues are straight forward.
Personally, I've developed with Java for over a decade, and I have never really understood when I should use one version or the other. Oracle, Eclipse Foundation, IBM, and the other big players have not done a good job of marketing the various offerings, nor have they done a good job of clarifying for engineers what they should be installing on their local machines, development and test servers, production, etc.
This is probably the clearest fact sheet I've seen yet, and the links to different distributions with a concise "Use / Don't Use..." rating is indispensable.
I am still seeing a lot of projects on 8.
New Scala projects are generally on Corretto 11.
No, seriously, we need the same thing for .NET
....ok
A lot of apps just got stuck there.
HTTPS everywhere is a positive, and it is a good thing to do.
Here are some pages that list some of the reasons:
The reason it doesn’t mention it is because it is a useless website.
openjdk 11.0.11 2021-04-20
OpenJDK Runtime Environment (build 11.0.11+9-Ubuntu-0ubuntu2)
OpenJDK 64-Bit Server VM (build 11.0.11+9-Ubuntu-0ubuntu2, mixed mode, sharing)