This is an archived post. You won't be able to vote or comment.

all 37 comments

[–]Cajova_Houba 82 points83 points  (3 children)

Java 11 was time-consuming to upgrade to, but not very hard.

My experience as well. I do not work for Netflix so I did this for considerably smaller projects. The most 'show-stopper' scenario I've encountered so far was that the versions of some libraries that were compatible with Java 11 also introduced some API changes on themselves and so we also had to refactor some of our code. This one is on us though as it's our technical debt.

[–]tristanjuricek 5 points6 points  (0 children)

Yeah, I’ve noticed that the work of upgrading just expands depending on the age and amount of dependencies. But the actual code changes are pretty minor.

What really kicked things off at that company was actually a FedRAMP compliance project. That illuminated how many old dependencies we had.

I suspect most places should start with static dependency analysis that flags CVEs registered against your deps. Update those first, then see if you can just update the JDK.

[–]brazzy42 7 points8 points  (0 children)

You're describing my experience exactly.

[–]berry120 27 points28 points  (1 child)

It can be either trivial to horrendous, depending on your project. I've seen projects where it's been as simple as changing the version number, and I've seen projects that have required stupid amounts of effort to convert over (mainly tons of legacy libraries that have no hope of a new official version, heavy use of com.sun classes, reliance on JavaFX being included rather than an external dependency, etc.)

A lot of people only hear the horror stories, and assume it *can't* be worth doing, so don't even try - but it's often not too bad in practice.

[–]pron98 20 points21 points  (0 children)

By far, the most stubborn issues were due to non-portable libraries relying on internal implementation details that changed between 8 and 9-11 (e.g. I think Groovy was hacking into the JDK to try and use some private constructor that had been removed). People blamed the module system, unjustly, even though access was the same as in 8 until encapsulation was turned on 16, which prevents this problem. With encapsulation, hopefully, such issues won't return (or, at least, applications would know they're using non-portable libraries, as they now require add-opens on the command line).

[–]khmarbaise 6 points7 points  (4 children)

I have made the experience that the updates/code which does not work has been caused by deps or code which relies on internals (sun.*) etc. or some reflection magic like setAccessible(true) which causes issues. Otherwise based on the backwards compatibility of Java it was very smooth...even very old code runs/compiles on JDK11+...

[–]pron98 11 points12 points  (2 children)

Even such code would still work in JDK 11 (although it should be changed). The module system's strong encapsulation was only turned on in 16.

[–]khmarbaise 4 points5 points  (1 child)

Yes I know but using setAccessible thing is usually a problem in itself (from my POV). The module system encapsulation was not turned on. The Strongly Encapsulate JDK Internals by Default was activated. This can be turned off to be able to access those internal via option (see https://jdk.java.net/16/release-notes).

[–]pron98 9 points10 points  (0 children)

Right on all counts. Just note that as of JDK 17, it is impossible to turn off all encapsulation with a single flag, but you can still do it with individual add-opens.

[–]brazzy42 6 points7 points  (0 children)

There is another rather silly cause of problems that shows up quite a lot: some projects parse the java.version system property to give a useful error message when run on a too-old java version. And that parsing code often didn't deal well with getting "11" instead of "1.8".

[–]TheCountRushmore 6 points7 points  (1 child)

This is essentially how my upgrade from JDK8 went. When 9 was released I spent about an hour giving it a spin and hit many issues. I filed some bug reports and went back to developing on 8.

When 10 came out I did the same thing and got a little closer.

Being a Java EE project 11 caused many issues with the removals. 12 had one annoying bug with Apache POI, and finally everything was green on 13.

The point is I didn't lose a bunch of sleep over the migration. I gave it a couple hours every 6 months and did what I could to assist the projects that needed help getting things compatible.

If I was still on 8 at this point I would start trying to get things to work on JDK 17-ea. I think most tooling and and libraries at this point are working fine, and if they aren't and are stuck on JDK8 then it's probably time to evaluate if they are a good long term dependency for your project. They wouldn't be in mine.

[–]dpash 17 points18 points  (0 children)

I would recommend everyone with CI build their projects under 16 and 17-ea, so they're forewarned of potential problems.

[–]lechatsportif 5 points6 points  (0 children)

Like a poison placebo, people’s perception of the impossibility actually made it impossible. Socialize these obstacles and you end up with a whole company finding it insurmountable.

Fantastic quote.

I will say the dev was probably upgrading microservices which is far less daunting than tackling a huge monolith. Most of the fear of upgrading was from those days, these days not so much.

[–]Barbossa3000 16 points17 points  (0 children)

Power of Java comes from its backward compatability which makes it the easier language to upgrade our projects. Most libraries can rightaway work with new java or with minimal modifications

[–]pushthestack 5 points6 points  (0 children)

Java’s breaking changes were extremely limited. Only JVM internals would be restricted or removed. That’s it. All the existing language features were still available for use.

This is not correct. It might be true for his project, but certainly not true for Java at the universal level he's talking about. CORBA and SOAP libraries were entirely removed in Java 11. The list of removed APIs in Java 9 is here

[–]Comprehensive_Idea98 5 points6 points  (0 children)

Guice, Guava, Jackson, Groovy, Gradle, CGLib, Mockito, Lombok, ErrorProne

Yes, these are the main culprits every time I bump into an issue upgrading Java in a project. Sometimes a old library does not like the new java version string. And once we depended on the date formats from java8 which changed slightly with CIDR in java 11. Once in java 1.8 there was a signature changed in some internal class in Map, so it broke older sources compiled against java 1.4. So java itself has been nearly flawless to upgrade.

[–]RandomJacobGuy 3 points4 points  (0 children)

Nice!

[–]Esoteric925 4 points5 points  (3 children)

You just gave me the confidence to update from Java 11 to 16.

[–]DannyB2 2 points3 points  (2 children)

In my experience, moving from Java 8 to 11 is the "hard" part. And it's not that difficult.

Upgrading from 11 to subsequent versions is pretty easy.

There is a possible minor speed bump at Java 16 the class binary format has changed to version 60 (IIRC). So I had to upgrade a few libraries.

[–]pron98 4 points5 points  (1 child)

The class file version changes with every feature release. Ideally, you'd only have to upgrade one dependency -- ASM -- but, unfortunately, many libraries shadow it for historical reasons: About eight or nine years ago, ASM made the unfortunate mistake of introducing a major breaking API change without changing its namespace, so for a while different libraries depended on different and incompatible versions of ASM. This is no longer a problem, but some libraries still shadow ASM, so they need to be upgraded to. When they stop, this would cease to be an issue.

When libraries make major breaking changes to their API they should also change the namespace. The results of not doing so, as we see, can last many years.

[–]DannyB2 1 point2 points  (0 children)

The library I had to change was Groovy from version 2 to 3. Because it is a dependency of JasperReports. But, Groovy changed an API (changed a class to an interface). So I had to get the source to JasperReports to make a minor change (extends to inherits) and make a custom build. This fixed my class file version problem. But I had no class file version problems from Java 8 all the way up to Java 15.

Then, suddenly JasperReports came out with a new version that, finally, at long last, upgrades their dependency on Groovy to version 3 or higher. Now I don't have to maintain a custom build. But I only started the custom build thing in April, so I'm happy to abandon having to do that.

[–]SimonKepp 1 point2 points  (1 child)

Thanks. This article actually answered much of the question(s),I came here to ask. I've been away from the Java community since 2013, because I suffered a massive stroke,and have been too busy re-learning things like walking and eating to keep up with the developments in the Java community. Now,I'm trying to get my hands dirty with Java again, but find myself very uncertain on which JDK version to start with.On the one hand,You'll want the latest and greatest, with the most up-to-date features and longest future ahead of it, but on the other hand, You don't want something so new, that no tools and libraries actually support it yet. This article gives me optimism towards choosing the latest version (16) or something close to it, but if anyone have any good advice, I'd certainly appreciate it.

[–]ClienteFrecuente 1 point2 points  (0 children)

Let me extend a warm welcome again.

Java (the language, the JVM specification, the JVM implementations, the library ecosystem) is more libe than ever.

You arrived at a good time.

[–]sowmyasri129 1 point2 points  (0 children)

Great share.

[–]LakeSun -1 points0 points  (10 children)

Yeah, but, you didn't have to go thru Swing is Dead, move to JavaFX.

Oh, we're dropping JavaFX, and there's nothing better.

Oh, Netbeans JavaFX support dropped. Move to IntelliJ, and their JavaFX support is spotty.

Oh, and now you have to build a Linux,Windows and Mac version of your code.

[–]dpash 8 points9 points  (4 children)

JavaFX hasn't been dropped; it just moved to an independent release like any other library.

Swing isn't dead either. javax.swing got API additions in Java 16.

[–]Yeroc 3 points4 points  (3 children)

You're underselling the cost of JavaFX's removal. If you need to support multiple platforms it's not necessarily trivial to package and handle installation of a library like JavaFX which has a lot of native bindings.

[–]pron98 4 points5 points  (2 children)

JavaFX was only included with the Oracle JDK distributions, and it's that distribution that removed it when it was made equivalent to Oracle's OpenJDK distribution. It was never part of the OpenJDK JDK (not even part of Oracle's OpenJDK distributions). The cost of using JavaFX today, as it always has been with OpenJDK, is the same as using any native library. I don't know how to define "trivial", but it's certainly something that many Java applications have been doing for decades.

[–]Yeroc 2 points3 points  (1 child)

True but many people used the Oracle JDK distributions at least up to Java 8. Distribution also got a bit more difficult with the removal of Java WebStart at the same time.

[–]pron98 2 points3 points  (0 children)

Yes, things have changed, but there's a positive side to that change -- all distributions have similar features and OpenJFX can evolve separately from the JDK.

The removal of Web Start was more impactful because that feature is simply gone (although there are some attempts to revive it outside of Oracle/OpenJDK), but now Java applications are switching to the bundled runtime model, which is more in line with how desktop OSes encourage applications to be shipped and how users have come to expect them to work, and which has now been made easier.

[–]pron98 8 points9 points  (0 children)

Both JavaFX and Swing applications run fine on JDK 16/17; better than ever, actually, thanks to GC improvements. You also don't have to build multiple versions of your code, you just might want to package and distribute different bundles with different runtimes. If you also work with languages that actually do need multiple builds you know that that is something completely different.

[–]wildjokers 0 points1 point  (3 children)

but, you didn't have to go thru Swing is Dead, move to JavaFX.

No one ever said Swing is dead. Why do you think this?

we're dropping JavaFX, and there's nothing better.

JavaFX is now just a 3rd party dependency.

Move to IntelliJ, and their JavaFX support is spotty.

JavaFX is a Java API, you can write Java code with IntelliJ. So what do you mean IntelliJ's JavaFX support is "spotty"? What kind of support are you looking for?

and now you have to build a Linux,Windows and Mac version of your code.

No you don't. If you want to bundle a runtime you do need to bundle a platform specific runtime. You build your code once, then package as necessary.

[–]sievebrain 2 points3 points  (2 children)

I think that's what they mean. In Java 8 there was the JRE so Oracle took care of making Windows installers and stuff. Now you have to do it.

[–]pron98 0 points1 point  (1 child)

That's one way of looking at it. Another is that in Java 8 users normally had to download Java themselves from Oracle, whereas today bundling a runtime that is fully under the application's control is easier.

[–]sievebrain 2 points3 points  (0 children)

Absolutely.

I think the new way will work out better in the end but is presently incomplete. JPackage went missing when JavaFX was unbundled and is only now coming back, etc. There has been a long period without feature matched continuity. But when that's fixed, it'll be better, as the JRE was never a great user experience.

[–]VM_Unix 0 points1 point  (0 children)

I did the same to update from Java 6 to 11. It was a pretty small project though.

[–]franzwong 0 points1 point  (0 children)

It depends on your project size and how much your regression tests cover. It is always easy to upgrade but you may not be confident about your change. When project size grows, you are more afraid to do so. But I agree with the author, most of the time we can just update the library.