 And so we just before starting and before we remove ourselves from the spotlight just want to give a standing ovation and or if you cannot stand up a sitting ovation to our hosts today. And Michael Punit, do you want to do the introduction? And you can use a chat to say hello and do your ovation. Sure, I think we can start maybe in like one or two minutes more. We just wait for few of the participants to join. Still 628 in my machine actually. I don't see the chat moving a lot. Please do innovation like you can just do our. Hello, I have been in chat also. Hello, there's no way off emoticons and chat also action. Is there one? I don't think Zoom chat supports a lot of the cons, but it's been a while so I've tried. Hello world. Yes, we can stop now. It's like 640 on my watch. Let me see if I can share my screen. Progress. Okay, first of all, like is my screen visible guys? Yep. Okay, sure. Hello everyone. Welcome to sure. So first of all, hope everyone is doing fine wherever they are in this part of the world and in the other part of the world like the Europe and the Americas. So welcome to the job. And today we have Prateek with us. He's a Java champion and he has also published a lot of books on Java and the related technologies. Currently he works at a zoo. And as part of the future tool, they are actually mentioning about, I mean, they're doing some sort of a joke tool across the world. And today we have one of the more very interesting topics in place. It's about Java 17, which has been recently launched and all of us are like quite excited about what's there in Java 17 and it's going to be the long term support for from the Java side. So welcome Prateek. Happy to have you here. Over to you with regards to the presentation. Okay. Thank you, Puneep for the lovely introduction. Let me go and share my screen so that you can see the presentation. And we'll just go ahead and get started. I will say about this presentation if you have a question, especially as we're looking at any of the code examples or any of the technical details or whatever. Please feel free to ask those questions. And I will do my best to keep an eye on the chat to answer those. Or you can just unmute yourself and also ask the question. So I'm happy to take questions as we walk through this, but we've already done the introduction. So I will skip this slide. If you want to reach out after the presentation, my Twitter handle is at the bottom. You can send me a direct message and we can continue the discussion there after this presentation. And this is the wrong URL, but let me get to it. There we go. So Azul is giving away $50 Lazada eGift card. So if you are in Singapore, please go and do a quick scan of this. I'm trying to find the chat. Where's the chat for so many different ways to do this? Hold on. There we go. I thought I had the chat up. There we go. Okay. I'm going to put the URL directly in the chat so you can enter to win the gift card with the URL that I just pasted into the Zoom chat, or you can just scan this. And I'll show it again at the end of this presentation also. And as Puneet mentioned, I work for Azul. So we have two different JVM builds for various different versions of Java, which are drop-in replacements. There's Azul OpenJDK builds, which are free and support available. And of course, our high-performance JVM called Platform Prime. So check that out. We like to think it's the best JVM in the Galaxy. In the Java Renaissance test suite, it beats OpenJDK by 37%, which is not a small number, of course. And of course, it's a drop-in replacement for the JDK. And there's no code changes. So one other thing, as Puneet mentioned, this is part of the Fujii Tour. So go check out Fujii.io. This is a great website with lots of content written by folks in the community. And you can also write content for Fujii. So it's definitely worth checking out if you just want to get up to date on some of the new developments in the Java space and surrounding ecosystem. Or if you want to write an article, it's a good place to go and publish your content, especially if you don't have your own blog. It's open and available to anybody in the community. All right. With that said, let's get started with the actual presentation. So again, if you have questions as I'm going through this, I'm happy to take them. The best time to ask a question is when you have it. You don't have to wait till the end or anything like that. And what we're going to do is this is broken up into three rough parts. I'm going to spend a few minutes just talking about the Java release cadence because I think a lot of developers are not necessarily confused about it, but they may just not be aware of some of the details around how Java releases are done today. And of course, we'll talk about all the features from Java 12 to 17 that have accumulated over the last three years between the long-term support releases. And of course, we'll look at some code examples. Okay. So first, let's talk about the Java release cadence. Now, a lot of people may not know, and this slide is wrong. I apologize for that. That should say September 2018 to September 2021, which is now. That is the amount of time that has transpired between the last LTS release. And what do we mean by LTS, right? So LTS means long-term support. And the intermediate releases are called non-LTS, or sometimes referred to as short-term support or feature releases. So that's Java 12, 13, 14, 15, and 16 are the non-LTS releases. But the reason why Java 17 is so important is because it is the new long-term support or LTS release since Java 11, which came out in September of three years ago. Okay. So something to keep in mind, right? The idea with non-LTS releases is to introduce features gradually, right? Not all at once. If you remember back in the days of Java six, seven, and eight, even nine for that matter, what happened is that there were many, many years between the release of those Java versions. So when Streams came out, for example, in Java eight, it had been almost five or six years before people had a chance to try out Streams in Java and try it out with their code base and see what things needed some minor tweaking and get used to using it. So the idea is that we introduce features gradually so developers can get an idea of what those features look like and provide feedback amongst other things and get ready their code base for the feature as it improves over time. So as you can imagine, aside from that, it's also meant to deliver features faster. And that's also part of the new Java release cadence that has been there in place since Java 11. So as you can imagine, Java has changed quite a bit over those few releases. And what we'll do in this presentation is we'll discuss some of the ways that it has changed some of the new features, some of the things that have been deprecated finally, and some of the things that have actually been removed. So for the first time in probably ever, things have actually been removed from Java. So we'll briefly touch on those as well. Now, one thing to note, as I mentioned, it's been three years since the last LTS release. And what Oracle has recently proposed actually around the same time that they did the release of Java 17 was that they want to change the LTS release cadence from three years to two years. So that means that instead of a new LTS coming out every three years, it will come out every two years. And in my opinion, this is a good move because that means that we're able to get the final versions of features faster and it allows us as developers to stay more up to date rather than using things that are three years old. We only have to worry about a two-year window in which new features and removals and fixes and other things have come in. But let's talk a little bit about how the release and feature cycles work for a few minutes because I think this is interesting to understand as a Java developer so that you can plan accordingly how to update your Java and how to basically plan around what's available, what are preview features and other things like that. So let's talk about incubator modules. This was introduced with JEP 11 and what this does is it introduces non-final APIs and tools to get developer feedback into the JDK releases. So the important thing on this slide is that these things are non-final. They're often referred to as preview features. That means it's an idea for you as a developer to preview what is there and start playing around with it and starting to understand how you can utilize these features in your code base and get an idea of what's coming. And basically be prepared for when a specific API or a specific feature becomes non-final. Then in that specific JDK release, you can start coding for it and putting it out. Of course you can code for it beforehand, but you just have to be aware that there may be changes to the way that that specific API or feature works. So again, it can result in changes or even removal of a specific preview. An example of this was the HTTP2 API, which was introduced in JDK 9 but was made final in JDK 11. So in JDK 10, you could have used the HTTP2 API, but because it was still in preview at that point, there was a possibility that it would have changed in some small or large way or maybe even completely removed. So this is just something to bear in mind. So similarly, you have preview features around this and this was introduced in JEP 12. And just like API and the different types of language features, the idea is that preview features are fully implemented, but may still have some kind of change that it might undergo in subsequent JDK releases until they're deemed to be final. The idea again is that with preview features, we get developer feedback, but it may lead to a permanent feature. And one of the things to note as a developer is that preview features must be enabled with the JVM flag. And what does that look like? So for example, we would say Java C – release version 17 – enable preview. Of course, this inherently means that you must have JDK 17 for this specific example with release 17 to work, but just in general, depending on whichever JDK you have installed and on the path of your computer or server, you would do Java – enable – preview to get all of the preview features enabled in your specific programming platform. Whether you're doing shell or if you're using IntelliJ IDEA or whatever IDE or tools you're using. One thing to note, there is a small difference between preview APIs and preview language features. As I mentioned one there are called incubators and other are called preview features. Preview APIs may be required for preview language feature. And preview APIs are generally part of the Java SE API, either in the Java or Java X namespace. So this is a visual diagram for how I think about this. So we have a preview API, which is used by a preview feature, which then both the API and the feature become final in some release of the JDK. So you can imagine that with a certain kind of feature there might be some kind of low-level API dependence on it. So we have to have the preview API stuff available so that a preview feature can build on that specific API and then eventually both those become final in a JDK release. And as we go through the presentation I think you'll see some examples of this to how this all actually works as I step through the different versions of the JDK, which is what we're going to do now. We're going to explore some of the releases since JDK 11 and we're not going to cover everything because that would take a long time to do. What we've done is we've picked out some of the nicer features and some of the things that I feel are more applicable for developers in terms of their day-to-day usage of the language. So with that said, let's start with JDK 12. And let's start with switch expressions in JDK 12. So let's think about the old switch statement for a second. So if we think of the old switch statement, there's no result that happens when you use a switch statement and inside of a switch statement you need to have a break to break out of the switch statement. And the other problem is that local scoping inside of a switch statement unfortunately is not intuitive. So this can be problematic as a developer. Let's have a look at what that looks like in code. Let's say we wanted to write some code where we have a switch that depending on the day of the week counts the number of letters in that actual day. So for example, Monday, Friday and Sunday have six letters in it, right? And Tuesday at seven and then Thursday and Saturday have eight and then Wednesday has nine. And you can, you know, everyone's written a switch statement so you can see what this looks like and how it works. And then we have a default at the bottom, which says that if it's not Monday, you know, Tuesday, Wednesday, Thursday, Friday, Saturday or Sunday, then we should throw an exception saying that that day was not found. Okay, so that's the old switch statement. Now switch expressions have been introduced in JDK 12. And it is different from a statement because if you remember from your programming basics, a statement is something that just executes procedurally some code. An expression is some code that returns a result that you then assign to a variable, okay? And what we can do with this new switch expression on top of the fact that it's an expression and no longer a statement is that we can also combine cases. So let's look at that previous example and see how we can rewrite that using the new switch expression syntax that was introduced in JDK 12. So I'll leave this up for just a second so you can see what it looks like. And as you can see, this is much, much nicer, right? So we say int number of letters equals switch day. So you can see that this is an expression because it's returning a value. In this case, we're going to return an int. And we've also combined the different case labels into single lines. So we say case Monday, Friday, Sunday, return of six. You can see we're using almost a functional style arrow that was introduced in Java 8. But if you have all this, you can see that if we flip back for just a second, right? So this was our old style switch statement. And this is our new style switch expression. As you can see, this is much, much nicer than what we previously had. And again, this was introduced in JDK 12. Okay. Okay, so someone asks, is there a functional interface implemented? We'll look at that a bit later. I think that Puneet was asked that in the update to switch expressions. And hopefully that will give you a better idea of what that looks like. But the short answer is that there's not really a functional interface, even though decided to use the arrow style for the assignment of the case statements value. Okay. All right. Also in JDK 12, there was an update to streams. There's a new collector that was added called team. And essentially what this is, is this is a merge type of collector that allows you to stream into and merge two upstream collectors using a by function. So what does that look like in practice? Right? It looks like this. So you have a stream, and then you have collector one and two, and then a by function combines and merges those in some way, depending on how you write the by function to get a result. So let's look at this in practice. And so say that you wanted to do an average of two numbers. You could stream some numbers, right? Using stream.of, which that's just part of standard Java. And then you can see dot collect, and then we have team in there. And then inside of that team, we provide a by function, which the first one basically just sums the numbers up. The second one counts the numbers. And then we have a functional expression. Sum comma and arrow sum slash and which if you recognize that algorithm, if you will, what it's doing is it's basically just taking the sum and then dividing it by N or getting an average. But you can see how we use the team operator here to essentially take two streams and then reply some code to both those and produce a result from it. So if you remember, this is what the basic idea of team is. You have two collectors and then you have a by function that operates on each value in those twice for two different algorithms or two different bits of code and produces a singular result. So there's also a question that says, are these collectors executing parallely on the stream? And the short answer is yes. There is something that was introduced in a later version of the JDK called the vector API, which unfortunately we don't have time to talk about, but you can go and reference that later. The vector API made some improvement in the way that you can do parallelization inside of the JVM. So we'll touch on that briefly a bit later too. But that's an excellent question. All right. So let's talk about JDK 13. JDK 13 included something which is pretty fantastic in my opinion and is overdue, which was the text blocks feature inside of Java. And again, this is the preview feature. And we'll see how this changed slightly in a later JDK release. But the idea is that you can use three double quotes and get multi-line strings. So let's have a look at what that looks like. So in the JDK 13 text block preview, you can now do this. You use three quotes. And of course, as you can imagine, this is handy for generating web pages. So if we look at what this does, it's multi-line, prints it out exactly. So one thing to note is that when you go and run this, it by default strips out the incidental white space, which is at the beginning. So you can see that even though in our code editor, it is invented over to the right so that it looks visually in the proper place within our code. When it's actually run, it strips out the incidental white space at the beginning of each line. You also notice that we have three spaces. And then we have a new line on the next line. And this is required to get this proper incidental white spacing. And just in general, you want to put stuff on the next line after the three quotes that you have to start a text block. Now, there are a couple of nuances around this is that if you don't want, if you go back to here, you can see that for the incidental white space on the last line where it says incidental white space, we have a bunch of spaces between the closed HTML tag and the three quotes that are at the end. And you can see that there's basically no new line after this. But say that you do want a new line. What you would do is you would move those three double quotes to the next line. As you can see from the executed example, it has added an extra line to the end of this. But you can also see that it has preserved the intentional indentation that we have with the incidental white space so that you get the code, the output is formatted exactly like you'd have it spaced to the first element or the first line to be specific in this case. So we'll come back and visit text blocks again in a few minutes when we talk about a subsequent version of the JDK. Right, and again, we're on JDK 13 right now. And the point behind the preview features is to put it out there like developer stride and provide feedback to the Java community process so that changes can be incorporated into that specific API or features. From JDK 12, when switch expressions were introduced to JDK 13, there were some changes made that allowed a more nicer way of introducing breaks into switch expressions was done. So what they did, this again is an example of an update to a preview feature. So from 12 to 13, the switch expressions change. And the only real change was that it now can use yield and not break inside of a switch expression. And they also introduced yield as a restricted keyword. So you don't have to panic if you use yield as a variable inside of your code base because yield is a restricted keyword which is only applicable inside of a switch expression. So if you're using yield in other places, you don't have to go and change it because it is a restricted keyword and not a full keyword in the Java language. But now what does that look like? We go to our previous example and use a switch expression and use yield instead of the arrow. You can see that this is what it looks like. You basically, you don't, you just say yield and the value that you wish to return and it will return that value for that specific case block. Okay. All right. So let's move swiftly on to JDK 14 and talk about probably the biggest improvement in my opinion and in the opinion of many others since JDK 11. That is records. So most of you probably heard about this. So we will take a quick tour of what records look like so you can get an idea of what is in the specification for this. Now, records are essentially a way of making data objects which have an accessor and a constructor on one line. And when you create a record class, it extends Java.lang.record. Let's go have a look at a code example. This is not a record. This is how we used to build DTOs or Java beans or whatever you want to call them. Okay. And we're going to use the case of a point inside of a graph. So we have a private final double XY. We have a constructor. And then we have a way of going and getting that specific data using a method, a method called to it. Okay. So this is how we used to write simple Java data classes or you could still write it like this, of course. But with records, this has changed. What we can do is all that code basically becomes one line. So let's flip back for a second to see how we used to write a Java data class. So we have, we declare the types of fields that are in it. We have a constructor. And then we have the accessor methods for those. Now, instead of all that, we could just say record point. We specify the type and that's basically it. Okay. So this is how we create a basic record inside of JDK 14. Now, it also creates generic records, record anything of type T, type T, as you can see there. And if we look on the fourth line here, you can see that we're not able to add record fields inside of a record. But we can have a static instance field if we want like so. So if you want to add an extra field in a record, you have to have it inside of the declaration. So public record circle, double radius, comma, double something else, right? So you can't just go in and add something arbitrarily inside of a record. You can add something when you declare the actual signature of the record itself. But you can add a static instance field as we've seen in this example right here. Okay. Now, look at some other things around this. Records obviously have a default canonical constructor that is generated, but you can override that canonical constructor like so. So we could say record tracks into X, Y and say you needed to do something to initialize that record. You could say public tracks. You can see the signature is exactly the same. And then we have some logic there. So if X is less than Y, blah, blah, blah, do some stuff. But when you create a canonical constructor, you do need to do a this dot X equals X and this dot Y equals Y. IE do the assignment from the passed in variables to the internal variables that reference the fields. Okay. Now this is a little messy. So there is an idea of a compact constructor. Right. So at the top way, you're using a canonical constructor which everyone is familiar with. But if you look at the second one, you'll see that we have record range in low comma in high. And then we just say public range. And then the low and high are inferred. And you can see we just do a quick check to say if flow is greater than high, then throw an exception or whatever. Right. So we've just added some business logic into the constructor. But in this case, we're using what's called a compact constructor rather than the canonical constructor or the old school style constructor that you're probably used to. Okay. Now, let's say that you need to do some more stuff around the constructor. You can also throw an exception by using that standard type constructor that we saw before. In this case, you can see we have a checked exceptions for how this works. So if your record needs to throw an exception, this is how you would do it. You would use the canonical constructor to be able to do this. And there's an interesting question from Penit who says, are records replacements for pojos? And the answer is yes and no. In my opinion, records are a replacement for what we would traditionally call Java beans or data access objects or just data objects in general. But it's not necessarily a replacement for pojos because a lot of people use pojos for things aside from just holding data. So records are meant to hold data just like data access objects are or data objects are. So if you have a lot of business logic, you would not necessarily put that into a record. One thing to note is that records are also immutable, but the immutability is shallow. So that means if your record contains some kind of object field inside of it, the reference to that object cannot be changed. But the underlying object, if it's, let's say, it's a point object that is contained within some larger shape object or something like that, then that sub-object can be changed. So it's a shallow immutability, not a deep immutability. However, saying that one thing that's interesting about records is if a record contains another record, then yes, everything is immutable because your entire kind of object tree for your, for that specific record, right? If a record contains a record as a field, since both are immutable, they will both be immutable. Okay. So, and someone, Pritosh says, is this similar to a tuple? The answer is yes. It is actually a tuple. Okay. So if you're familiar with that term, it is definitely a tuple. And somebody else, Nita says, is Lumbok dead? That is a good question. Lumbok is a little bit of a polarizing project or tool in the Java universe. I personally like to use Lumbok, but I have friends who I respect who don't like to use Lumbok for a variety of reasons. So I understand what Nita is trying to ask. The short answer is that maybe you don't need to use Lumbok with Java records anymore. Okay. And someone else said, actually, I was thinking that we wouldn't need Lumbok anymore. But the reason why I said maybe is exactly what Michael said. Lumbok actually does much more than just provide data objects. And there is a vast variety of constant, a vast variety of different annotations within Lumbok that help you do more things besides data objects. So yes, all excellent questions. Thank you for asking them. Okay. One more thing. If we use a default constructor when we, sorry, if you use the compact constructor inside of a record when you create it, don't forget that you have to run a this to go and go set those variables to make sure that the data is set accordingly to the internal fields on a record. Okay. All right. So a couple of more things. Let's go have a look to see how if we wanted to have extra things passed in, but not stored as a field, the way that you could do this is you could use a canonical or standard constructor. And then you can see we have this X, Y there to set the internal field. But you could see that the record declaration on the first line is slightly different than the constructor declaration on the second line. So that's what you're doing in this case is you're saying, I want a constructor with three things passed in, but I actually only need two fields in the record X, Y. I don't really need Z to be stored, but I might need it to do some validation or do some computation. So we can do that like so. Okay. And this is a complete example where you have an exception and you're using a canonical constructor with more arguments or parameters than the record would normally take. And you can see that we do some checking and we set the X and Y to the internal value of the fields or we just pass it up to the default constructor for it to set it. Okay. All right. So if we're again going to the default constructor or sorry, so this is the canonical and this is the compact constructor, we still want to go and set the or invoke the default constructor by doing this two comma three so that the fields get set appropriate. Okay. So let's talk a bit about using instance of. Right. So remember Java is an object oriented language. And there's this new feature called pattern matching based on instance of and it uses something called flow scope. So let's get into this for a bit. And again, this is JDK 14. JDK 14 in my view was the release that introduced the most number of features since 11. So you probably have done this before where you say if object instance of string, go and do something with it. In this case, go and print out the length of the string. Right. But we have this instance of here and it could be a little bit annoying that we have to do this quite a bit in our code base. So the pattern matching instance of preview introduced this new way of essentially doing an inline quote unquote pattern match of instance of. Now, this isn't pattern match matching in terms of the way that we're normally used to thinking about it using like, you know, regular expression or something like that. What it does is it allows us to say in this case, if object is an instance of string, we introduce this new almost variable name here called s. And then we say system dot out print line s dot length. So let's flip back a bit and have a look at the difference. So what this is doing is this is doing in in implicit cast from what we're doing the check of the instance of from. Right. So we say object instance of string. If that's true, then we do a cast of object to a string and then we're able to go and call the string methods on it. But you can see that this is a little bit nicer and is a little bit more expressive in terms of how we actually write this code. Right. So we can just say if object instance of string that we give it a temporary variable. And then we don't have to do a cast anymore. And of course in this specific case, because of the scoping, the else statement will not have s inside scoped inside of it because it just doesn't make sense. Right. Because if the object is not an instance of string s, then we don't need to use that s. We would just use OBJ to reference that thing to do something else with it. Right. Okay. Let's look into this a little bit more. Let's say that we want to do some kind of additional check. We say if object instance of string s and s.length is greater than zero, then go do something. Right. And this works because we're using an ampersand ampersand or logical amp. So as you know in Java, well almost every programming language, when you do a logical amp, the left side must evaluate true before you even execute the right side of a logical amp. So hence why this is possible. Right. Let's dig into this a little bit more. And if we use an or expression, right, and we say in the last one, object instance of string s or s.length is greater than zero, that will give you some polar error because in a logical or both sides of the logical or have to be executed for it to be able to pass the or test. But as you can imagine, this is not allowed as you have to do the instance of s first. So you would have to essentially do a embedded if to be able to do that. You're not able to go and string two different tests for the pattern match of the instance of in this case. Okay. So one thing to remember of course is that we're using flow scoping here. So we can say that we're able to scope inside of the instance of block as we've done previously. So that in this case, if we say if oh is not an instance of string, then we just return, but that s is available subsequently because we have the specific logic that says that if it's not that then put it into scope. Okay. So that's what flow scoping means in this case. All right. So as mentioned before, as we go from different versions of the JDK and there is a preview API or a preview feature, there is the very high possibility that as long as the feature is in the preview state, then there can be changes to it. And we need to be aware of that as we're coding that there may be change to a preview feature until that feature is deemed to be final in some way. Okay. So one of those changes was the text block were changed slightly as the team that works on these features on the Java team got developer feedback. So essentially what they did is they added a couple of new escape sequences, a slash four at end of line and a slash S for trailing spaces. So let's see what that looks like. It's easier to explain in code. Okay. So two new escape sequences. Right. So say that you want everything to be on one line. You can use almost the shell script style of the slash. So this line will not slash contain a new line in the middle. Blah, blah, blah. Right. So you can guess what this does. If you've ever written a shell script, the slash means basically this is not a line break line break. I've just made this line break here for readability purposes. So this will be one single line. And then the other thing, as you can see in the second example here is that if you actually do want the white space not stripped at the end of a line, what you do is you use a slash S and that will tell the Java runtime to preserve up to where that slash S is the actual white space. Okay. So that's one of the things there in terms of how you deal with white spacing inside of a text block. All right. So let's quickly reference Jeff 393, which is the forward memory access API. I don't want to go into too much detail on this because this is actually a topic all into itself. And if you're interested in this, there's a recording of this by my colleague Carl D who talked about project Panama in detail. So the foreign memory access API is part of the project Panama set of features, which is meant to be a replacement of JNI. If you're not familiar with JNI, JNI is a way for Java to call down into native code and native libraries. Right. And this is an example of an API enabling a new feature. So the foreign memory access API enables everything that's in project Panama, which is a new way of accessing native libraries because JNI has been for many, many years, very confusing and frustrating way of calling into native libraries from Java. So they finally addressed that with Panama. And as I mentioned, my colleague has a nice presentation on project Panama, which is also part of the Fuji tour. So if you all want to do it here, contact Eertron and he can get that lined up also. So anyways, we already looked at this. Sorry, I don't know where that slide came from. The other nice thing that was introduced in this JDK was the helpful no pointer exception. If you're familiar with how no pointed exceptions work, if you did a.b.c.i equals 99 and anything the b, c or i was no, I'm sorry, the a, b or c was no, you would get the first exceptions that printed, which is basically no pointer exception on that line. Unfortunately, that's not very useful because is a no, is b no, or is c no. So what was introduced as part of this is a more detailed no pointer exception message, which you can see in the second exception, it says cannot read field C because a.b is no. So that basically tells you that, well, b is no. The annoying thing about this feature, unfortunately, is that you have to explicitly enable it, at least currently, by adding this flag to your Java runtime. It's dash x, x colon plus show code details and exception messages, which I think is actually the longest flag that you can pass to a Java runtime. I don't think I've seen a longer one, but anyways, you do have to explicitly enable it. I'm not sure why they didn't enable it or have it enabled by default. It might be because there are a lot of tools that use log scraping to be able to get to be able to do stuff. Everyone has probably written some kind of Java log scraper to watch for certain kinds of exceptions. So maybe that's why they didn't enable it by default because people have written tools that scrape Java logs or look at Java logs in runtime to do air reporting or whatever. But you do have to explicitly enable it to use this feature, but I think this is really nice and handy because now I don't have to turn on a debugger or write extra test cases to be able to isolate when this kind of error does occur. I can just look at it and I know exactly where the error is when we do some kind of chain access to objects. Let's move swiftly on from JDK 14 to JDK 15. The major thing that was introduced in JDK 15 was this concept of sealed classes. Now what does sealed classes actually mean? Let's have a look at this to get a better idea. Moving forward. This was introduced in JEP 360 and what sealed classes allows you to do is give you control over what can be subclassed. It has to be in the same module or package and the method signature looks like public sealed class shape. I'm just making up that class called shape permits dot dot dot. We'll look at that in just a second, right? But again, remember that has to be in the same module or package and the idea is that it allows you to control who or what can subclass something. So let's say we have a class called shape and then we have subclasses triangle, square and pentagon. If we were in standard Java, anybody could subclass shape unless you mark shape as final in which case nobody could subclass shape, okay? Which obviously is not the perfect solution. That's what sealed classes fix. So for example, you could create, you could say public sealed class shape permits triangle, square and pentagon. And so if you created a, tried to create a subclass called circle that extends shape, you would get an error because in the sealed class, only things which are explicitly permitted using the permits keyword are allowed to extend or subclass that specific class, okay? So there's some interesting nuances around this, right? All subclasses must have inheritance capabilities explicitly specified. So we can restrict subclasses to define set of different things as we see in the first line of code, public seal class triangle permits those things but extend shape, right? So we can restrict subclasses to define set in this case. The second code example is we prevent any further subclassing, right? So we say public final class where extends shape in this specific case so that the subclass cannot be extended anymore, right? And of course, if we want to unseal a class, we are able to do that. We could say public non-sealed class pentagon extends shape, right? So that means we can reopen the subclass. But remember that everything needs to be within the same package or the same module for the ceiling to or the ceiling rules that we've talked about to be applicable, right? So as mentioned before, preview features are able to be updated until they are deemed to be final. And so the records was also updated in this version of the JDK. So the main thing that was done is that there's this concept of local records now, okay? So it's almost like a local class and it is implicitly static. So let's look at this example, right? So we have list seller, find top sellers and then inside of this find top sellers method, we declare a new record that we're only going to use inside of this method, right? So you could see, I'm not going to walk through all the code here because what we care about for this specific code block is the way that we have declared a record inside of a method rather than at the class level. So in some ways, some ways, this is like almost like anonymous inner class, but we have a named record inside of a method and then we can go and use that record to hold some data as we do some computation. In this case, we're basically going and extracting or I should say inserting a object called seller into a sales record and then we're using that to do some functional Java style programming or coding to apply an algorithm to go and get the top sellers essentially to sort all the sellers in terms of their sales by storing the data inside of an encapsulated sales record object. Okay? All right, let's move forward. Okay, and of course, these new features often go hand in hand or a new API or a new feature is incorporated into another new API or feature and one of those things is records working with sealed classes. So we can create a public sealed interface car permits or red car, blue car, etc. and then we can create a record from that. We say public record red car implements car public record blue car implements car, right? So we were using a sealed interface to go and limit the classes that can implement this interface and in this case, those classes are records. So here you can see some of the new features in JDK 11 working together, namely sealed classes and records. Remember, records are just another type of class. When you create a record, it's actually implementing Java.lang.record as its base class, okay? All right, so let's get to Java 16. We're slowly getting to Java 17 and actually Java 16 didn't really have a lot of things inside of it, right? So the main things that Java 16 did was that it made the pattern matching stuff that we have been discussing so far and the record stuff that we've been discussing so far, it took it out of preview mode and it made it final. So that means now you can use the pattern matching stuff and records with the knowledge that they will not be changing from this point onwards, okay? So the other thing is that it added the two lists to streams and it added something called period of date. All right, the other things that were added in JDK 16 were the vector API. But note, this is not the vector class, it's the vector API. This is essentially a way of allowing parallelization of code within Java to get performance, or parallelizable performance. Again, it's not the vector class, it's a vector API and I'm not gonna go into detail on it because I think it is useful in certain use cases but it's not something that most people would generally use unless they're building some kind of high performance computation stuff in Java. For example, if you work in financial services or if you work in scientific computing, it is interesting to look at this. So I just wanted to mention that you can have a look at the vector API if you work in an area that requires parallelizable or high performance computation in Java. The other thing that JDK 16 introduced was the JEP 389 or the foreign linker API, which again is part of project Panama of accessing native code and native libraries in Java, again, project Panama and it's a Panama presentation hour by itself so we're not going to jump into that here. So those are the major things in 16. Pattern matching and records final, there's a new two list in stream, there's a period of day thing for working with time and these three things that we just talked about. So let's move on and see what's in here. Now we have pattern matching for switch. So here's another example where we have two new APIs or features where they are working together. So a switch is typically limited on what type you can use and this can be a little annoying sometimes as a Java developer it's like why can't I just use this to do a switch statement. Now with pattern matching it gives us a little bit more expensive capabilities. So it expands to allow type of patterns to be matched. So if we have a look at this you'll see we say switch O if the case is known which I think this is really handy say go and do this. If it's a string then cast it to a string and then go and do this. If it's a color or a type of color go and do this, etc. I think this is actually really handy if nothing else for the ability to do a null check directly inside of a switch statement. So the switch statement and the expression can now use the pattern matching stuff that we talked about i.e. where we would normally do an instance of to check to see what kind of object we can do this directly inside of a switch statement. And I think this is one of the most interesting and useful features in JDK 17 or just in Java in general in the last few years. I think having the ability to work with types in this flexible way or do specifically to do type matching and testing in this specific way is actually very very useful in a practical sense. We've done some variation of this in a lot more code. So if we want to look at a slightly more complete example of this we can also say that if the pattern matching for instance of in a switch does not match something we can have a default to have some kind of an object out of this in case there is no match and then if we wanted to just instead of using an object as the base here if we wanted to use for example the sealed class as an example we could check switch, shape, triangle square and pentagon for shape but notice if we use a sealed class inside of this pattern match for a switch statement we don't need a default why don't we need a default if we're using a sealed class as the base for the switch expression because a sealed class can only have a finite number of defined types. If you remember a sealed class you say a sealed class can only be extended by these classes specifically so in the case of shape we said that the shape sealed class can only have a triangle square and pentagon subclass and no other subclasses can exist for this class so when we use a sealed class as part of a pattern match for a switch expression we know exactly what's possible for it so there's no need for a default because there can only be these three things there can never be something else besides these three because it is a sealed class and we have explicitly stated that there are only these kinds of subtypes for it so along with what we've seen for the instance of pattern match previously we can also do some guarded pattern if you look at the highlighted area in this specific example we say case triangle T and end T dot area is greater than 25 I think again this is really nice because it allows the Java developer to write more expressive code on less lines of code what we would have to do in the past is we would have to write a separate have an if block and etc etc and it would probably get a little messy in this case we can just say if it's triangle and execute this method in a triangle if the area of it is greater than 25 then say it's a big triangle or it's a small triangle right but you can see the guarded pattern here is we say what's the primary pattern i.e. does the instance of match this specific type and then have a conditional and expression attached to it so we're almost near the end here let's talk about some of the things that were removed from the Java Universe in JDK 17 so this is something that's new for us because typically in the Java Universe we do not see things actually getting removed what we see is things just get deprecated and lots and lots of things just get deprecated and this can be kind of it's kind of nice in a way because if you've written code 10 or 15 years ago like I did you can sleep good at night because you know that your code will always run up until now but it is nice that things are getting removed and the reason why I think it's nice is because it helps to keep the Java language and the JVM runtime as small as possible which I feel is important in this cloud universe that we live in now everyone on this call probably runs some kind of Java application on the cloud if not all their Java apps on the cloud and you know we put stuff into a Docker container and we run in a cloud type of restricted environment whether it's a VPS whether it's Kubernetes or OpenShift or whatever so it's nice that things are getting removed because now we can have a more what I like to call lean and mean Java runtime okay so for example in JDK 17 are leaning up to JDK 17 the CMS garbage collector was removed what you would use instead of the CMS the Concurt Mark and Sweep garbage collector is you use the G1 garbage collector or you can step up to a professional grade a garbage collector which is Azul Prime as I mentioned before Azul Prime is 37% faster for example in the Java Renaissance test and if you use Neo4j Azul Prime can run the Neo4j query and analytics 167% faster etc etc so anyways JDK 14 removed the CMSGC JDK I'm sorry that was 14 JDK 17 removed the experimental AOT and JIT compilers that were previously introduced I believe in JDK 9 and they were introduced originally for work on Growl VM which some of you may be familiar with the Oracle Labs project but they basically decided that it wasn't necessary to keep those experimental AOT and JIT compilers around so they were removed so the other thing that is kind of a big deal but not really is that the security manager has been deprecated for future removal now this may sound like it makes Java less secure but actually it doesn't the security manager is a relic from our days of writing Java applets embedded inside of a web browser believe it or not so the Java security managers actually not really used in real world non-applet scenarios and I don't think there's a lot of people still writing applets today anyway alright so almost on the home stretch here JDK 7 did finalize some internal JDK APIs so JDK 9 introduced encapsulation of internal JDK APIs which means that certain things like Java dot miss dot unsafe were now encapsulated in JDK 16 the default became to deny access to those encapsulated in internal JDK APIs that you are not supposed to use and then in JDK 17 they basically made it so that you can no longer access those internal JDK APIs however some exceptions were made for example for Java dot sorry son dot miss dot unsafe is still available okay but most of the internal APIs if you're using them in your code are no longer accessible with JDK 17 but with JDK 16 you were able to allow usage of those by setting a flag in JDK 17 they're not even usable anymore as for most Java developers maybe 99.99% of Java developers you don't care about this because you don't use internal son or JDK APIs anyways so let's talk about the different versions of the JDK you can use the Azul Zulu builds of OpenJDK which are again 100% free and open source they're fully TCK tested so that's one of the unique things is that Azul Zulu JDKs of the OpenJDK versions are fully TCK or TestKit compliant tested for JDKs version 6, 7, 8, 11, 13 and 15 available on many platforms and of course drop in replacement for Oracle JDKs or any other JDK for that matter okay so finally a few words the six month release cycle seems to be working well by allowing Java developers early access let's say or preview access to these features it gives us Java developers the ability to go check out things like records and to try out things like switch expression and to start thinking about planning how we will start using this in our code base whether we're refactoring things or we're writing new code so it seems to be going well it allows us to have new Java features and releases and enhancements faster which in my opinion is a good thing and because of this release cycle Java is adding features to give developers great ways to code faster okay there is a bunch of stuff that we didn't cover for example project Panama and the new vector API and things like that so this was not an exhaustive cataloging of all of the different types of features API changes and other things in JDK 12, 13, 14, 15, 16 and 17 so just be aware of that okay and with that we will start actually there was PD mentions that is there a replacement for Nashorn in Java 17 so yes you are correct that's one thing I did not mention is that Nashorn which was the JavaScript interpreter that was built into Java for a long time was removed in JDK 17 and the short answer to your question is I do not know if there is a replacement for Nashorn in Java 17 I think you can still use Nashorn in Java 17 by simply pulling in the library for it but I am not familiar with that specific thing okay so with that I'm going to stop sharing and did we stop sharing yep okay I'm going to stop sharing and take some questions or some comments I will also reiterate that if you are in Singapore and you wish to be entered into the prize giveaway for $50 gift card I will put the URL again inside of the zoom chat here okay alright so any questions or comments on the various different topics that we've talked about okay so there is another question right about the ZGC garbage collector is it going to be available as well I believe ZGC is still available but I think a larger question is why do you want to use GC you are better off using let me go double check the worst things like I said the CMS removed typically nowadays you want to use the G1 garbage collector but I will say that there are certain use cases where ZGC might be better I don't know but PD who is the person who asked that question if you want to get in touch with me or by email or something please let me know what your specific use case is for ZGC and we can have a discussion about it and I might be able to give you some more insight or information on what is a good replacement for that questions or comments doesn't look like we have any more final call going once for questions or comments going twice I actually have one more question you can say it generally we always see use cases where we have to build some low latency apps I remember you were mentioning something about that is there any features or anything that you want to talk about so that we can go and refer to what is that feature about all these recent versions of Java or probably explore this GC and this can help you out you know you are specifically mentioning low latency applications the Vector API is one of them that is good for doing concurrent computation and that does not necessarily factor into the garbage collector strategy there is unfortunately I can't remember it is way too early in the morning for me so I can't remember there is another garbage collector that was introduced I think in Java 11 or 12 I think it was in 11 actually I don't remember the name of it but that garbage collector was aimed specifically at doing more parallelization inside of the JVM but I am trying to think in terms of pure language features I think records are good because they are essentially a built in way of having a DTO type of object so that will definitely affect garbage collection the fact that those objects are immutable will also have an impact on garbage collection but of course you would have to have millions upon millions of those objects really to make a difference in the garbage collection a strategy around it one of the nice things about working in Java is that the garbage collector has gotten much better just in every release like the CMS and the G1 and then there are commercial garbage collectors which are part of for example Azul Prime Azul Prime has nearly real time no latency garbage collector so that is something that is worth checking out of course but in terms of the other code type of things I think one thing that I would be careful of is using the text blocks when I say careful I feel like using a text block because when we do strings strings take up a lot of space inside of the heap so I feel like a text block would probably have a positive impact on low latency and garbage collection but I would really test to verify that that is just my feeling so the one thing I do wish that was introduced was some kind of string interpolation along with text blocks because I think that everyone has done this where you say string A plus string B plus string C and we have it all over the place and it looks at least from just a developer's perspective it looks very messy as a developer so I wish they would have introduced string interpolation along with text blocks maybe they'll do that in a subsequent release of JDK but where I'm going with this in terms of performance is that if they had the ability inside of just straight Java code to do inline string interpolation I believe that there could have been some essentially either JIT based or GC based optimizations applied to a built in string interpolation type of methodology or feature that would improve the ability for low latency and garbage collection for those interpolated string types I'm going kind of deep here hopefully you understood what I was trying to say but that feature I think would give the designers of garbage collectors and also people who designed optimizations the ability to apply immediate and long term JIT optimizations that would have a really good impact on reducing latency and helping garbage collection be more efficient is what I'm trying to get at but that feature does not exist today so we're just calculating and having some fun right now sure thanks for the details so any more questions I think we're almost at time and also to Puneet and the Singapore Java user group members thank you so much for having me as I was saying when we first started hopefully we'll be able to do this in person sometime next year instead of over Zim I mean thanks for taking it really it was a pleasure listening to the session, really enjoyed it and I think our members would have learned quite a bit in myself as well so thanks to you thanks Ketujan for helping with this and really appreciate all of you so happy to have you here for the new sessions as well so let's just keep these topics as well for sure thanks for taking it have a good evening or good morning good morning to you bye