Facilitating the Spread of Knowledge and Innovation in Professional Software Development

Write for InfoQ


Choose your language

InfoQ Homepage Presentations Life beyond Java 8

Life beyond Java 8



Trisha Gee talks about Java 8, wondering whether we should move to a later version, which one to choose, what sorts of issues we might run into if we do choose to upgrade, and how the support and license changes that came in with Java 11 might impact us.


Trisha Gee has developed Java applications for a range of industries, including finance, manufacturing, software and non-profit. She has expertise in Java high performance systems, is passionate about enabling developer productivity, and dabbles with Open Source development. As a Developer Advocate for JetBrains, she gets to share all the interesting things she’s constantly discovering.

About the conference

Software is changing the world. QCon empowers software development by facilitating the spread of knowledge and innovation in the developer community. A practitioner-driven conference, QCon is designed for technical team leads, architects, engineering directors, and project managers who influence innovation in their teams.


Gee: Hello, I'm Trisha [Gee]. I'm a technical advocate for JetBrains. I'm the Java advocate and IntelliJ IDEA advocate. My job involves staying up-to-date with what's happening in the Java world, so that I can help other people stay up-to-date. This used to be easy back in the olden days, because Java moved at an interesting enterprise-level pace, and now Java is moving much more rapidly. The aim of this talk is to give you a TLDR version of what's happened in the Java ecosystem since Java 8 came out. What was that, three years ago now?

Before I get started, who's using Java 8? Most of you. Who's using the version before Java 8? You have other problems. This talk might not be for you. Get onto 8 first. Who's using 9? Three people. Who's using 10? Five people. Who's using 11? Oh, loads of you. Great, awesome. This is about the representation of the version numbers I've been seeing through my extensive research by using Twitter as a top research tool.

I want to talk a bit about the ecosystem since Java 8. A lot of people have this problem where upgrading past 9 sounds scary, particularly with the module system, and Java breaks everything past 9, which is not true, but there's definitely a perception of that. On top of that, since Java 11, there's been a few concerns around, "I don't want to have to pay for Java. What's the deal with people starting to charge for support now?" I want to talk a bit about this, because a lot of people are super happy with Java 8, thanks very much. "I think I'll just stay here. I've got lambdas and streams. It's all I ever wanted from my language. I don't need modularity, so I'm not going to go beyond Java 8," which is something that I've been seeing, like I said, through my super scientific research on Twitter, which only allows you to put four values into your questionnaires anyway. This doesn't even represent the people who are using 7, 6, or even, heaven forbid, earlier than 6.

The majority of people who are using 8 or above are using version 8, not surprisingly, and then some people are using Java 9, some people are using Java 10, and a surprising amount of people already on Java 11, even though it's only been out since last September. This might be an unexpected shape of the poll results for a lot of people. You might expect to see more of a curve of people being on 8 and then slightly fewer being on 9, fewer being on 10, and even fewer being on 11. The shape of this curve is one of the things I want to cover in this talk.

Releases, Updates, Licensing & Support

I'm going to cover the new release cadence, the progress for updates for versions of Java, the licensing and support changes. I'm also going to cover a bit about what you might get out of using a version of Java beyond Java 8, and I'm going to hopefully cover some pointers for upgrading the migration path from 8 through to 11 specifically. I'm hoping that a lot of this news isn't really news to people, but like I said, this is the kind of summary condensed version of stuff that's happened in the last couple of years news-wise that you need to be aware of if you're running Java inside your organizations.

Firstly, we moved to a six monthly release cadence, six monthly release cycles. In the old days, we would get Java every two years, three years or sometimes six or seven years between versions of Java, which is one of the reasons why I think enterprises loved it so much, because it's nice and stable. But now, since Java 9, we have releases every March and every September like clockwork, and this is a much better way of working. We know this from doing continuous delivery and continuous deployment. If we say we're going to release on a specific date, we just release the features that were ready then. And then if they're not ready at that point, we release them in the next release. We just have this nice, predictable release cadence.

Now, obviously, Oracle didn't want to support every one of these releases for three years because at some point, they'll be supporting like six or seven different versions of Java. And as developers, we know it's a pain in the neck to support something, more than one version of something, at the same time. Instead, with the six monthly releases, each release will be supported for the six months of their life. By supported, I mean having updates available, so updates for 9, 10, and so on and so forth for six months, until the next release comes out.

But obviously, not everyone wants to upgrade their version of Java every six months, so every three years one of these releases will be designated a long term support release, specifically Java 11 and I assume Java 17. Java 8 is also a long term support release. You get sort of mini releases every six months, 9, 10, and then you get long term support releases every three years, so 11. And that explains the results we saw where people are on either 8 or 11. Because if you are 9, you should have migrated to 10. And if you are on 10 you should have gone to 11, because now 9 and 10 and no longer supported.

However, this is actually Oracle's story. This is not everybody, everywhere, every vendor, every JDK. This is a story from Oracle. And the Oracle story is if you want the long term support, in terms of support and updates, you have to pay for it. If you don't want to pay Oracle for updates to your JDK, you have to update every six months with each release that comes out. If you want the long term support from Oracle, you have to pay for their commercial JDK?

Specifically, I'm just going to give the legal stuff. Starting with Java 11, Oracle will provide JDK releases under an open source license and under commercial license. This replaces the historical BCL license. So traditionally, you had two different- I'll come to that in a minute. The point is, “This sounds frightening and overly complicated. Talk us through it.” This comes from that classic film, "The Lego Batman Movie," which is a very popular movie in my household as you might have noticed if you saw my children earlier. It does sound very complicated, it sounds confusing, it sounds frightening. We have to pay for Java from now on. So let's talk through some of the implications of this.

Firstly, Oracle now has two different JDKs. They have an OpenJDK, which is the free one that you can download and use in production for free, no problem. And they have a commercial JDK, which you have to pay for if you're going to use it in production. Obviously, if you don't want to pay, use the OpenJDK version. From Java 11 onwards, the Oracle JDK builds and the OpenJDK builds will be essentially identical. In the past, people were a bit worried about using OpenJDK because they're worried that OpenJDK is not the same as the Oracle JDK that they've been using forever. I'm assuming that most of you are using the Oracle JDK, because that's where we go. We go to the Oracle page, we download the Oracle JDK, and we use it without thinking about it. And that's why I want to talk a bit about some of these changes, because this is no longer the case.

However, from Java 11, the OpenJDK is the same as the Oracle JDK, and that includes the commercial features that you used to have to pay for in the Oracle JDK. So Mission Control and Flight Recorder are also now part of OpenJDK. This is actually a good thing. Oracle has worked hard to put all the useful features from their JDK into the OpenJDK. From OpenJDK, there are many builds, not just the Oracle one, not just the Oracle commercial build, which is also based off OpenJDK; there are a bunch of different builds. And there are a bunch of different vendors to choose from, some of whom you will see here in the exhibition hall like Zulu and IBM. So Oracle is not the only game in town. The one I want to point out as being an interesting choice if you're not really sure how to tread this whole landscape, is the AdoptOpenJDK. Martin will find this very exciting because he's kind of leading a lot of the efforts on AdoptOpenJDK.

If you go to the AdoptOpenJDK website, you will see that you can download a JDK for 8, 9, 10, and 11, including long term support. You can actually have two different JVMs too, the HotSpot or OpenJ9. You can see it's supported on a bunch of different platforms, Linux, Windows, and Mac, and so forth. This has long term support and free updates for a longer period of time. It says here, "In addition, every three years one feature will be designated long term support release," which we know. "We will produce long term support releases for at least four years," and this you don't have to pay for. You don't have to pay for support. You don't have to pay for updates. This is a community driven effort, but it's got the backing of a bunch of the well-known names in the Java space. So this would be my default place to go to to look for downloading a free-to-use JDK based off OpenJDK.

But as I said, there are a bunch of different options. This will produce LTS releases for at least four years. This is great because it lets you slowly migrate from 8, to 11, to 17 with a bit of overlap. You can actually see it says the end of availability for Java 8 is at least September 2023. So some of you are going to take away from this talk, "We don't need to upgrade from Java 8 until 2023." Fine, but you're going to have a lot of pain in a few years' time.

Why Bother?

That's kind of like the high level summary. With some of this stuff, it's a bit involved because it changes the way we think about support updates and licensing for Java. There is a session later on today called, "Is Java still free?" which I assume is going to go into this in much more detail. There are a bunch of the vendors on the panel for that. So if you have any questions or doubts around that, I would highly recommend going to that session, because that's designed to address a lot of these issues.

The question is, once again, "That sounds scary and complicated. Why should I bother migrating from Java 8?" Let's look firstly at language features, because I'm assuming that we are developers and technical people, and what we care about is the language features. Once again, I'm going to go to my highly scientific Twitter to figure out from the people who are using versions of Java later than 8, which are the features they use the most? Which ones are the most interesting? The first one is JShell the REPL. Let's have a quick demo. This would not be a Trisha talk without least some demos.

JShell - who has used JShell before? Who has heard of JShell? Good, that's good. Who knows what a REPL is? All right, I'll just do a really, really quick demo. The point is to be able to run small snippets of Java from the command line, which we could never do before because we had to have a whole class with public static void main(), blah, blah. But now we can do, including tab completion, we can just run stuff from the command line. And you see, you get all your nice tab completion there. And you don't need semicolons, progress. You could do a bunch of other stuff. You can, obviously, define variables. You can have like, int i equals five. I put a semicolon on just by pure habit. You can mess around.

One of the nice things about using JShell is you can mess around with the new features without having to create a whole class or testing framework to mess around with stuff. We're going to use var because we can. I can define these. I can also define anonymous variables here. And then I can list them using some of these commands. I can see what all my variables are. I can do things like I can define methods, so I can have void printSomething(). I use tab completion because I'm used to living inside an IDE. Let's say someVal. Here, I do need a semicolon. And I can create this method even though it's got a forward reference. I haven't defined someVal yet. It says I've created it, but I can't invoke it until I declared what someVal is. Then I can say someVal is something. And then I can call printSomething().

I can kind of build up a bunch of states, and a bunch of variables, and I can play with stuff. I can also do things like I can save stuff into a file, so I can reuse it later. I can run scripts and things like that. So it's kind of nice. I'm not really sure how many people are really using effectively scripting for Java. But it turns out that a lot of people are finding it quite useful. Quite a few people were quite happy to see that JShell is built into the language. They can just kind of use it to try stuff out as early as possible.

One of the nice things about JShell, as you saw, it's like an independent command line thing. You don't actually need to do anything with your existing applications to start using it. You can just download Java 11, or Java 12 if you want, and use JShell completely independently from anything with the rest of your application. It allows you to sort of get started, get up and running early on and quickly without impacting anything that you have at the moment. Of course, the big feature from Java 9 was var. Not really that surprisingly, loads of people are quite happy to be using var in their code. Because less typing is what we're all about. Because typing is really tiring when we're a Java person. Typing is not the difficult thing.

Most of you probably know of, or have used var. I'm just going to talk through a couple of examples because I'm the advocate for IntelliJ IDEA, so it would be really stupid we have a talk without any intelligent idea. No, because it's really useful. Java 10. I turned on the inspection in IntelliJ IDEA which says, "You could turn these things into var. You can use var." I can just automatically replace that with var, that's fine. Great, so it's marginally less typing. Big deal. It's kind of useful when you've got things like generics because that can start to be a bit unwieldy. You don't need to declare the types on both sides. So let's turn that into a var. Fine, I kind of know this is an array list of person. I should be able to see. Well, IntelliJ tells me in really tiny writing that this is an array list with type person inside it.

Now, with var, it's going to use the type information obviously on the right to determine what the type is. Var doesn't mean dynamic typing, by the way; it just means you don't have to type the types on both sides of the equal sign. So if you have something which is defined as a list, but is an array list, then when you turn that into a var, it's no longer actually a list. It's now an array list. In terms of using it with interface types, then you may or may not want to use var. You might want to define something specifically as having the type of the interface.

var is not like a magic keyword, you just put it everywhere and say, "Let's just get rid of all the types on the left hand side." It's something to think about. You use it when it makes your code easier. For example, we're not going to use it here because now my code doesn't mean anything. I don't know what that type is. I don't know what type comes from this method. I don't know what type this variable is. If you have less than optimal names of your variables, you might not want to be using var, but you might want to use it in places like this where you have like really long types on both sides of your equals.

The other place you might want to use it is somewhere like this. That looks fun. This is a genuine thing. I didn't make this up. This is when you're iterating over something, I don't even care about that type. And that is a good place to have a var. So yes, var is nice. It is not a magic fix-all thing. It is something that requires you to think about, "Is it the right thing to do?" And will it remove actual useful information, or is it just going to hide a lot of the boilerplate that Java allegedly has? Java does have boilerplate, but not all boilerplate is a bad thing.

var is good. People like var, especially if they've come from other languages, like, I don't know, Kotlin, for example, that my company invented. People like var, and people like var combined with things like Lombok to try and reduce some of this boilerplate that's in Java. For many of us who've been programming in Java forever, it's not really a big deal because we're used to working this way. It's not a big deal. But for people who are used to using other different types of languages where the boilerplate is, well, more focused on readability and less boilerplate, these features are quite useful.

My favorite feature from Java 9 is the convenience factory methods for collections. This is one of the things that gets used by a bunch of people. So all of these people love it. They think it's amazing. Like I said, if I put enough tweets on here, that's going to sell you on moving to Java 11. Because people in Tweeter think it's good, therefore, it's a good thing, right? That's how life works these days. Twitter dictates technology.

Let's have a look at this, because it's my favorite feature. We're going to look for Java 9. Obviously, this came into Java 9. For all of you using Java 8, in the olden days, we would declare a list, a set of values like this. Your Arrays.asList(), and you sort of use it as if it was an immutable, unmodifiable list. But actually it's not, because you can't add to that list, but you can change the individual elements on that list. So it's actually not unmodifiable, but we all used it as if it was. We have to wrap it inside in unmodifiable list to make it unmodifiable. In Java 9, you don't have to do that. You call List.of(), and it's much more readable.

It's kind of nice for list. It's really nice for set, because creating a set was a bit of a pain. You have a list, and then you put it in a set, and then you wrap it in an unmodifiable set. I don't understand why this feature wasn't in the language earlier. Now, you just say Set.of() and you get an unmodifiable set. Similarly, for map, you had to do stuff inside a static initializer. Now let's see if this formatting is going to go mental. You can do a Map.ofEntries(), which the formatting went a little bit mental. Let's see if I can get this. That's because you wrapped that in a weird way. You can do Map.ofEntries(). That's okay. It's not terrible, especially if you start putting your static inputs in for all of these things. And then reformat that. That's nice. Marvelous.

So yes, it's a bit more readable. It's a bit better than putting inside a static block. It's much more interesting when you have fewer than 10 entries, which probably some people do. If we have fewer than 10 entries, let's get rid of these, then you can use a Map.of() and then it just uses convention of key, value, key, value, key, value. It's just, again, a bit less boilerplate, a bit more readable, particularly useful for things like test code. But also I used to work at MongoDB and I used to create maps all the time inside that. Because when you're putting stuff into a document store, you use maps. And this is a much nicer, easier syntax for creating maps.

In Java 10, one of the things that came in is the ability to collect into these unmodifiable lists. That's really useful. You can just straight away change your streams to collect into unmodifiable lists, sets, etc. Another new feature which came in in Java 9, is new methods on the Stream API. This was a feature which I thought was a little bit missing from Java 8, the ability to do things like process this stream until some condition is met. This is .takeWhile(), the other example is .dropWhile(), so ignore this stream until some condition is met. So it's just a nice little addition to the language for working with streams.

A feature which came into Java 11, is predicate.not. Now, you can negate stuff. There was a bit of argument about this, like do we really need a predicate.not? Surely we can just use an exclamation mark, because that's the same thing. But it's all about readability, and the whole point about a lot of the language updates for Java recently have been around readability. For example, if you like using method references, which some of us do and some of us don't (What did I say it was? Java 11.) - instead of doing this, you can't use a method reference if you not it. You can say predicate.not. Let's static input that. You might prefer that syntax just from a readability point of view. It's really about personal preference. So that's something that came in in Java 11. Some people love it, and some people think, "What's the point?"

Then over the course of Java 9, 10, and 11, we've been getting additional methods on optional. I actually think this is one of the most interesting things about the most recent versions of Java. Java 8 had optional. Optional is good. It's a really nice way of saying, as a return type from an method, saying, "You might get something. You might not." Don't misuse it in terms of having it for fields, and for parameters, and all the rest of it. It's really there just for when you ask for something like, "Find me a something." Optional can say, "You got something," or, "You didn't." With Java 8, you can work with it in a fairly simple way. You can say .ifPresent(), or .isPresent, and .get(). And it's kind of fine, but the recent methods that have been added on 9, 10, and 11 make it a little bit even easier to use.

For example, optional. Instead of having to do something like this, where you do an .isPresent(), and you have to do a .get(), and then an else- which you don't have to, because you could have done an .ifPresent() there, but you still have the else hanging around which is a bit clumsy. I found that optional was a bit difficult to work with in 8, ifPresent or else was - I don't know if it was 10 or 11. But now, you can just give two lambda expressions. So you either do that if it's present, or you do something else if it's not present. That's one of the nice things. That's Java 9. You’ve got .or() on Java 9 as well, which gives you an alternate optional. So you either return this optional value or you return a different optional value. You can use stream to work with optional inside streams in a slightly easier way. You can return the value of an optional or throw a default exception, the not found exception. I think this is a useful method for when you're actually doing in the middle of the migration. This is like a step on the way to using optional in a more effective manner.

And then in Java 11, obviously, we're used to using .isPresent() in Java 8, but we can actually use .isEmpty() in Java 11. Again, a readability thing. Obviously, you could say not.isPresent(), but some people prefer explicitly saying, "If it's empty, do this thing." What's this? Oh, yes. So yes, that's just IntelliJ being too smart. So yes, so some of these methods on optional just make optional easier to work with. So if you are working with optional in your code base, you'll find that 9, 10, and 11 give you some nice new ways of working with it.

Java 11 comes with a built in HTTP client. The things that people like about this is having a really good built in HTTP client will solve our headaches, so you don't have to use any dependencies. But also, it's non-blocking reactive streams, HTTP 1 and 2. So this is something that a lot of people are interested in from a Java 11 point of view, especially in this current world of asynchronous reactive programming.

Another feature which I thought was interesting from Java 9 was multi release JAR files; not applicable to a lot of enterprise developers, but it's applicable to any of us who use other libraries, which most of us do. This allows library developers to create a single JAR file, and you run it on whichever JDK you're running on, and that JAR file can use features from whichever version. JUnit 5, for example, can use features from Java 11 if you're running on Java 11, or it won't use those features if they're not available due to multi release JAR files. And then you don't need to say, "I'm going to download the version of JUnit 5 for Java 9, for Java 10, java 11." It's just a single JAR file. So it's very useful for the library developers.

Of course, Java 9 had Jigsaw, which everyone is very excited about it or not. And of course, we're supposed to call it the Java Module System, not Jigsaw. So it is useful for a bunch of people specifically, again, for library developers because they can encapsulate stuff that you're not supposed to be able to touch. That's the point. But it also can be useful for enterprise developers who want an excuse or a mechanism to actually properly separate the concerns inside their applications.

The most interesting thing to me I think about module system is it allows us to do things like have JLink. JLink, I think, is very interesting. This allows you to package up your application and just the bits of Java that you want, and create a much smaller deployable, and deploy it into the cloud. For example, with the JDK being modularized, there's a whole bunch of modules you could be using. But if you're just using java.util or java.logging, like two or three of those modules, you use JLink to create a single deployable with your application and just the bits of Java that you want. They can be much, much smaller.


I'm running out of time, but I want to do a demo of this because I really like the potential of this, particularly for deploy into the cloud, for example, and it can help save you money. For example, I'm calling JLink here from Java 11. I have to say which modules I want to package up. These are the modules from the JDK itself. My application has two modules; one is called three, one is called four, and then the module I really care about is three. So it's just the magic incantation you need to use. You do that and then JLink will go away.

Of course it does, because I created it. That's what I was going to get rid of. Oh, well, you know what? Let's just put it into three-image2. So it puts that into a directory called three-image, which has got things like lib and bin. By going to bin, you can see I've got java here and javaw, just the tools that I need from Java. If I go back out again, the size of that directory - that's not the one I wanted, but anyway, it's the same thing. What did I just do? That's not what I wanted to do. Slash-S, three-image2, and that's 40 MB.

I can create much smaller packages to deploy my application with. I think this might be one of the reasons why we don't have a JRE anymore, because we can actually just create our own runtime environment for our application. Not surprisingly, I am of course running out of time, as usual. This is a classic Trish talk at QCon. How long does this talk take? JLink is very interesting and could potentially save money for lots of people.

In the future, we also have a bunch of other stuff coming. Java 12 is coming out in two weeks time. Java 12 has switch expressions. I've got a demo for this too. But let's do a quick one. Switch expressions, I mean, a lot of people would say you shouldn't be using switch anyway, because switch is really nasty. And it's possibly a sign that you're not doing polymorphism correctly. But there are cases where you do get values and you want to say, "If I get this value, give me one of these." Now, with switch expressions, you can use a much smaller syntax to do the same thing. And you don't have to put the break statement everywhere, and you can use the nice pretty lambdas and stuff. There's more information about this on the IntelliJ blog. It was published last week. So if you're interested, go and have a look at the blog post on that. That's coming in Java 12.

Of course, in the future- and this is going to be Simon's talk tomorrow, I believe - we’ve got things like Project Amber, Valhalla, Loom, a bunch of other stuff. I know that a lot of people here in London are interested in things like value types for performance, and there's loads of cool stuff coming in Java down the line at some point in time.

The Business Doesn’t Care about Language Features

(Oh my goodness, I have five minutes left and I've got 20 more slides to get through). The business doesn't care about language features. We care about language features, because it makes our job easier. I say we- I'm assuming that we're all developers, or developer-minded. So you can't sell the business on upgrading to Java 12 because of var, for example, they just don't care. But what they do care about is things like performance. So generally speaking, each version of Java is generally faster for a number of different reasons. Anytime you upgrade, even if you don't make any changes, even if you don't make use of anything, you generally find that the performance of your application is better.

Obviously, test, measure, see if it's true or not, but often you get free performance improvements. Specifically, in the last few versions, there's been a lot of optimization, some memory use. For example - that's garbage collectors, and we used things like the way that strings are represented. I've seen a few cases where people have been able to decrease the memory footprint of their application by almost as much as 50% because the way that strings are now represented. This is quite interesting. Again, particularly if you're running in the cloud and you care about memory use.

There have been a lot of changes to the garbage collector. In Java 9, the default garbage collector is G1. And then a bunch of changes went in to help improve the performance of G1 even further. If you care about the garbage collection, obviously, people tend to go, "Performance equals garbage collection in Java." It's an element of it, but it's not the only aspect of performance. But there are a lot of changes there. Coming in later, we have even more different types of garbage collectors, more improvements to those garbage collectors, and so on. So, again, these are the sorts of things that if these garbage collectors and these changes work for you, you get some free performance improvements moving forward.

Obviously, what the business really cares about is cost. Now, I believe that moving forward to a later version of Java can help reduce costs of the company, by which I mean actual money type costs, in terms of things like using JLink, in terms of things like better performance, lower memory usage, and so forth. So you can reduce costs. But there's also another cost which I think is important. If your organization is trying to hire Java developers, which most organizations are at any point in time, if they have a big Java shop, and if you're going to be stuck on an older version of Java for a long period of time, it will be more difficult to attract developers going forward. At the moment it's fine, because they're probably fine working on Java 8. But going forward, people are not going to be interested in working on legacy systems going forward. So I guess that's kind of a personal thing from the developer point of view.

The other reason which I think is really interesting to move on and migrate now, is to get yourself on the six month release train before it gets away from us. Because we may be worried about getting over the hump of Java 9 to Java 10. But if we leave it much longer, it's just going to get worse and worse. That big difference between Java 8 and Java 17 is just going to be a very difficult bridge to span, a gap to bridge. So I think it's worth trying to get onto 11 now, so that then we can start thinking about testing against each of these six monthly releases. Even if we stick on 11 and we don't plan to migrate to 12, 13, 14, we plan to migrate to 17, we can be running each of these six monthly releases in CI to make sure that we stay up to date for as long as possible.

This is a quote that my old boss Dave Farley used to say to us quite a lot, "If it hurts, do it more often." Which sounds kind of crazy, but the fact is that if you do it more often it actually hurts less over the course of time. If you leave it, like I said, if you try and migrate to Java 17, it's going to be very painful, particularly since Oracle has said they are going to start deleting stuff. Deprecated means deprecated. There may only be a year's worth of notice between deprecating something, and actually removing it from the language. So we need to get onto this release train now and do it more frequently.


Now, this quote does mention the word pain, so let's quickly talk about the possibility of pain when you're migrating. People are a little bit worried about modularity and Java 9, because they hear that modules are broke everything. Generally speaking, it shouldn't break everything. And my experience is that actually when I tried to migrate, I've taken a couple of examples of open source projects that were running on 8 or actually lower, and run it on 11, I've actually found that it didn't break the way I expected it to. So that was really interesting. I don't think modularity is necessarily the problem that people think it is. Plus you don't have to use modules. So there's all this pain with Jigsaw, but if you don't use Jigsaw, then you probably won't incur any pain.

There will potentially be some pain from missing classes or missing methods. This is from a combination of different sources. So modularity, encapsulated internal APIs, so stuff that we shouldn't have been using in the first place has now gone away. It's now invisible to us. So yes, there are some things that have gone away because they have been encapsulated. In Java 11, some modules were deleted from the JDK, so there's no more Java EE stuff, which means specifically JAXB. That's what a lot of us were using as part of the JDK. That's now an external dependency. Korba has gone away. I hope you weren't using Korba. And Java Effects has gone away as well. But again, these are all external dependencies now. They're just not part of the JDK anymore. The JDK is no longer going to be this big, fat, bloated everything.

Tips for Migration

I've got no time left to go over some tips for migration. It's just a really quick set of tips, though. Firstly, run your application on a new JDK. You might find it just works. There are a few examples where I tried it out and it actually just worked. I was really surprised by this. Our inclination might be to go straight to trying to compile on a new JDK, but you don't have to compile, you can just run it on the JDK.

If you do have compiler warnings in your code, do try and fix those compiler warnings before you migrate to a later version. They are there for a reason. Particularly deprecation warnings, they are going to be taken much more seriously going forward. So if you've got things which say, "This is deprecated. It might go away," or if you've got warnings which says, "This feature will be removed in Java 9," there are warnings like that. Then do address those before you start trying to migrate. They're there for a reason.

Update your dependencies. This is kind of a quick win. Generally speaking, you should keep your dependencies up-to-date anyway for security reasons, because old versions can potentially have all sorts of problems with them. So you should keep your dependencies up-to-date anyway. I understand that it can be difficult to migrate to newer versions of Spring, or newer versions of big frameworks, because there's a cost with that. But you really do want to keep these as up-to-date as possible. The later versions of a lot of the stuff we're using, latest versions of mocking frameworks, testing frameworks, Spring, etc., they all work just fine on Java 11. If you update your dependencies, you could find that all of your problems go away. You may also need to add new dependencies like JAXB and other dependencies that are now external to the JDK.

Definitely update your build tool. Earlier versions of Gradle or Maven will not work with Java 9 onwards. The latest versions work fine with Java 11 that I have seen in my limited experience. So you do need to be on the latest version of specifically Maven and Gradle. Yes, I have been using them on Java 12. They did not error noticeably.

And then once you've done all of those things, then you can consider compiling against the JDK and maybe start using these shiny new features. But I found a lot of people were using latest versions, for example, Java 11, they're not using the new features, but they are at least compiling and running against it. Then you can start introducing the new features, the same way we did with lambdas and streams. We started gradually using these features where it seemed applicable.

In Summary

So quickly, in summary, Java is changing and it's changing much faster than it used to. It's no longer the nice, slow, and stable enterprise type language that we're used to. Modern Java can help you. This is a good thing. The recent versions of Java have focused on things like reducing boilerplate, increasing readability, but also of course, things like performance is always improved with each release of Java.

Upgrade now and reduce any potential future pain, and if possible, keep upgrading with the six monthly release cadence. You don't have to put it into production, but I would highly recommend running the latest version of Java in your CI environment at least, assuming that you have a CI environment. I really hope that you do.

All the resources from this talk are here. There are loads more links to all the stuff I talked about, things about the new licensing, things about the support, things about updates, stuff about all the language features, and there's a link to a bunch of stuff about actual step-by-step migration guides from Java 8 to 9, or Java 8 to 11. There's much more depth at this URL here. Thank you very much.


See more presentations with transcripts


Recorded at:

May 07, 2019