loading...
Cover image for Let's revisit Java in 2019

Let's revisit Java in 2019

tech_sam profile image Sumit ・13 min read

It's been 6 years from now since Java 8 was released and people are still not able to digest the features of it, wasn’t Java 8 a fantastic update to the language?

Lambdas and streams were a huge change and have helped to improve Java developers’ productivity and introduce some functional ideas to the language.

Then the new guy came into the town Java 9, and although the module system is really interesting for certain types of applications, but uncertainty around how painful it might be to migrate to Java 9 left many applications taking a wait-and-see approach, happy with Java 8 and some are still living with the old buddies Java 5-7.

But now Java has a new version every six months, and suddenly Java 13 is here. We’re all still on Java 8, wondering whether we should move to a later version, which one to choose, and how painful it might be to upgrade.

In this blog we’ll look at:

  • Why upgrade from Java 8, including language features from Java 9, 10, 11, 12, 13?

  • What sorts of issues might we run into if we do choose to upgrade?

  • How the support and license changes that came in with Java 11 might impact us?

Since Java 11, there have been a few concerns around, I don't want to pay for Java.

I want to discuss a bit about this, because a lot of people are super happy with Java 8, thank you 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.

This is what I am hearing and finding everywhere from people who are at least some concern about their tech stack. This doesn't even represent the people who are using 7, 6, or even, heaven forbid, earlier than 6.

Lot's of changes that happened in the last couple of years news-wise that you need to be aware of if you're running Java inside your organizations.

Releases

Firstly, Java has moved to a six-month release cycle.
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.

As a developer, we know it's a pain in the neck to support something, more than one version of something, at the same time. Same thing applicable to Oracle also and 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.

Instead, with the six-monthly releases, each release will be supported for the six months of their life.

By support, 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.

Obviously, not everyone wants to upgrade their version of Java every six months. So here is a catch, 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 people are on either 8 or 11. Because if you are using 9, you should have migrated to 10. And if you are on 10 you should have gone to 11, because now 9 and 10 are no longer supported.

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.

There are a bunch of different Open JDK vendors to choose from some of them are Zulu, AdoptOpenJDK, Amazon Corretto, etc. So Oracle is not the only game in town.

Because of these different options, 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 blog, 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.
So the question is now that sounds scary and complicated.

Why should I bother migrating from Java 8?

We are developers and technical people, and what we care about is the language features.

People who are using versions of Java later than 8, which are the features they use the most? Which ones are the most interesting?
Here we are not going to discuss detail about these features, that we can plan for some other time.

With the help of JShell, you can 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.

Jshell

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.

You 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. People were happy to see that JShell is built into the language. You 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,13 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.

Most of you probably know of, or have used var.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.

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.

The use of var also makes your code concise by reducing duplication, e.g. the name of the Class that comes in both right and left-hand side of assignments as shown in the following code snippet:

ByteArrayOutputStream bos = new ByteArrayOutputStream();

Here, ByteArrayOutputStream repeats twice. We can eliminate that by using the var feature of Java 10 as shown below:

var bos = new ByteArrayOutputStream();

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.

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 an 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 a list. It's really nice for a 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 will get an unmodifiable set.

Set<String> set = Collections.unmodifiableSet(new HashSet<String>() {{
     add("foo"); add("bar"); add("baz");
}});

can be used now as

Set<String> set = Set.of("foo", "bar", "baz");

Same thing is applicable to Map also.

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 that came in in Java 9, is new methods on the Stream API. This was a feature that 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.

Stream<String> stream = Stream.of("sam", "sumit", "jhon","nancy");
 List<String> list = stream.takeWhile(name -> (name.charAt(0) == 's'))

                  .collect(Collectors.toList());

the output of this code will be [sam,sumit].

Stream<String> stream = Stream.of("sam", "sumit", "jhon","nancy");
    List<String> list = stream.dropWhile(name -> (name.charAt(0) == 's'))

                  .collect(Collectors.toList());

the output of this code will be [jhon, nancy].

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 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, when you have to use Optional.isPresent(), and you have to do a .get(), and then an else- which you don't have to, because you could have done a .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 within 8.

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 return a different optional value.

 blog.ifPresentOrElse(  
  this::publish,  
  this::notifyThatNothingWasPublished
 );

Java 11 comes with a built in HTTP client. 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.

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 the module system is it allows us to do things like have 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.

This is not the end of the world it is just I don't want to make this blog a marathon 😌.

Reason to upgrade

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 13 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. 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's 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.

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.

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.

Discussion

pic
Editor guide
Collapse
thorstenhirsch profile image
Thorsten Hirsch

Java is hip again, indeed. The language has received great updates as well as the JVM (and there are several to chose from). However project jigsaws can be a pain in the ass du to errors like this:

cannot access class jdk.internal.misc.Unsafe

Or this one:

...because module java.base does not export jdk.internal.misc to unnamed module.

And then you have to find out which VM args to use. Is it "–illegal-access=permit"? Or "--add-exports java.base/jdk.internal.misc=ALL-UNNAMED". Or even "--add-opens=java.base/jdk.internal.ref=ALL-UNNAMED"? That sucks.

But on the plus side there's jlink. With jlink it's possible to build Docker containers of less than 100MB that includes Alpine Linux, a stripped down JDK 11 and your app with all dependencies. That's really a big achievement and compensates for the trouble that the Java module system has caused.

Collapse
aussieguy profile image
Anthony Bruno

Nice article! The increased cadence of releases has allowed a lot of cool features to be added to Java. Even the smaller additions of List.of() and Map.of() has saved me heaps of time!

The new HttpClient is also a nice replacement for UrlConnection. I wrote an article about it here.

Collapse
tech_sam profile image
Sumit Author

These new changes and collection factory method really reduced lots of boilerplate, at least now I am feeling happy as a Java developer after so long 😉

Collapse
mustabelmo profile image
Mustapha Belmokhtar

thanks @sumit for the article.
In this example

Stream<String> stream = Stream.of("sam", "sumit", "jhon","nancy");
List<String> list = stream.dropWhile(name -> (name.charAt(0) == 'a'))
              .collect(Collectors.toList());

The drop-while conditon is name.charAt(0) == 's'.

Regards

Collapse
tech_sam profile image
Sumit Author

@mustapha , thanks for your valuable time to read and pointing out the mistake, fixed it :)

Collapse
brogrammerben profile image
Ben

Java 11 supports cgroups out of the box (came in Java 10) which are necessary for resource limits on containers, a handy feature in Kubernetes. Just another reason to upgrade to keep up with modern tech stacks.

Collapse
geoffreyarthaud profile image
Geoffrey Arthaud

Many Thanks for your article. I personnally like the strategy you suggest : you dev and push code in production with Java LTS release (Java 11 today) ; and you thoroughly test every following version (12 and 13 today) on your CI !

Collapse
fultonbrowne profile image
Fulton Browne

Great article, I have bean a java developer for 2 years and I didn't know about the var feature, thanks for mentioning it, it should save me some time.

Collapse
daviddalbusco profile image
David Dal Busco

Me neither I didn't knew about var.

In Javascript nowadays using var is kind of discouraged. It's kind of funny that in Java it's the contrary.

Collapse
thorstenhirsch profile image
Thorsten Hirsch

Well, but the reason is obvious, isn't it? A "var" has completely different implications in these 2 languages.

Thread Thread
daviddalbusco profile image
David Dal Busco

I did not say the opposite.

Collapse
prathamket profile image
prathamesh

Very well written.. but yeah there are some other dynamic programming languages available in market to overcome the underfloor stack. I have been using Java for long time on just putting my hands on python, I found python really easy and interesting. Yeah Java is generally faster and more efficient than Python coz it is compiled language.but python had really great libraries and most of the major libraries are available with free licences for commercial use.