 Yes, I think most of you guys have seen Andres already because he came, is it twice Andres? You came to our Java user group once in real life, once virtually, it's the first one today. And yeah, so I really say before Andres is a Java champion, worked for many cool companies, currently working for Oracle, very involved in all the build systems like Maverick, Gradle, and so on. And currently working on a new, very cool project called Geraldies, and it's going to present what Geraldies is. Thank you very much, Michael and everyone else for joining us today. I'm going to click on the share screen button, and we have about 45 minutes before we get the second speaker, Dimitri, who has joined us already. And so we have plenty of content for you today, and feel free to ask any questions at any time. Okay, here we go. And click on play so we can see the slides. Great. So Geraldies, now the thing is that we as Java developers, developers in regular, what we do is, it can be said that we move data or translate data into pixels, and translate those pixels back into data. And in order to do that, we create programs. And these programs or binaries have to be released and have to be sent and being available to our users. And there are many ways to do this, right? So here we go. So my name is Andres. I like open source, like Michael said, and I also love the groovy. So why did I start this particular tool, which is pretty much close to a year ago? So here was my situation a few years ago. I write tools because I want to, this is something that I like. And I also write UI tools using JavaFX, previously, I used to do it with Swim. So writing a JavaFX application is quite a straightforward task. The second part or the next part is, well, providing those binaries for that application to your user. You might think, that's so easy. I mean, you have already compiled your project and created some sort of binary. Just push it into a website and you're done, right? Well, not necessarily, because once you start to see how your users like to consume binaries, say, for example, if you are an OSX user, you might prefer to use Homebrew. If you're a Linux user, you might prefer to use Snapcraft or RPMs or Deviant packages. Your Windows user then is either Winged, Chocolatey, Scoop or something else, right? It's not just a binary jar that you produce, and then your user should be happy. Related to this task of just making sure that the binary can be released, you also have to craft documentation and release notes, crafting all these different packages, such again, Scoop, Chocolatey and the others, require additional metadata. Some of that metadata can be obtained from your project, but again, it's just a handful of different formats. So this thing is easy to say, I'm just going to produce a binary and put it somewhere available to my users. But then once you start to see all the different other tools that are available, well, things get complicated. So that was my goal. I had a JavaFX application that I wanted to make available to my users. So what I was just waiting for something to happen is figure out how I was going to make the most of all the DOS 3 distribution channels. I stumbled into two other tools. One is called GoReleaser. This is for the Go programming language, and there is called JBank, which is for the JDM. So GoReleaser takes your Go sources, creates binaries for all matching platforms, and then goes ahead and creates a Git release and a Homebrew package and Scoop and Chocolatey and many other things. And it also creates checksums. It can sign the files with PGP and so many other things. Now, this is the tool that I saw and I immediately thought, wow, I want that for Java, but there is no such tool yet. At the same time, I saw JBank, which produces a set of binaries as a SIG file, a tar file and jar files, and also pushes those binaries to different distribution channels. The same was I just mentioned with GoReleaser. The way that JBank does it is by crafting specific scripts with Bash and Gradle. So the way that it works is specific to the JBank project. So the author of JBank, Max Anderson, a good friend of mine, we started talking many months ago and we thought, what if there was a way to use GoReleaser or if there was a GoReleaser-like tool for Java that looked at all the lessons learned from JBank so that we can adapt what JBank did, but opening up for any other Java project. And this is exactly what JRReleaser is. So you can find the project at JRReleaser.org. That is the website and contains documentation and links to many things. And so we will continue to see a little more. So what is exactly JRReleaser? It's a command line tool that allows you to create releases. You can create a Git release on your typical Git services, GitHub, GitLab, Git and a few others. And you can also create or package the binaries into different formats or platform specific packages. And finally, you can announce a release to different communication channels. So this is what happens. You supply, you build your binaries in the way that you couldn't really do it using Ant, Maven, Gradle or something else, whatever it is. Then you supply those binaries with a metadata model to JRReleaser. And then JRReleaser can simply say, I'm going to release these things, create a Git release on the target Git services, because so repackage these into the package platform specific packages that you saw earlier. And you can also announce different channels. Now, GoReleaser does everything in one go. Whereas JRReleaser, we decided to split this into smaller pieces. So this is the full diagram of all the commands that you have to your disposal if you happen to use JRReleaser. The full release command, the orange one, does everything in one go. So that actually creates the changelog for your project when you want to create a Git release. Capitalists checks us with different algorithms that you can configure. Optionally, science artifacts with PGP signatures that you also configure, uploads to different HTTP servers or Java architecture and creates a release on the Git service, you've got GitLab. The second column, it will prepare the manifest and the metadata for different platform specific packages, for example, could be the formula or the CASC for Home Room, or it can create a Docker file if you want to do Docker images as well, or create a manifest for a scoop and chocolate. Package actually creates the platform specific package here. In the case for Docker, it creates the image. And for Choco, it will create some sort of binary. A few of these happens. And published is where it published the actually generated things into the place where it needed to be. Could be additional and Git repositories. And finally, the announced step. There are many different communication channels that you can use, such as Twitter, SDK man, Microsoft Teams, MatterMos, Slack, of course, all of it. You might notice there is a box at the bottom, the black one called Assemble. JR Releaser assumes that the binaries are built by other tools. But the Assemble step allows you to build cross-platform J-link releases or native image executables using Growl VM. Whether you like to use a different tool to build these native executables, or would you like to use JR Releaser, it's up to you. The point is that once you have the binaries, then the rest of the operations can work. So in terms, I already mentioned a few services, but here's the whole gamut of services that we integrate with. So if you want to create a Git release, then there is the most typical options, GitLab, GitHub, GitHub, Codeberg, is service currently open in Europe. I think it might be available also worldwide, which is based on GitHub. And if none of these options work for you, you can also use a generic Git option, such as you can target Amazon or other Git services. But some of the features are not fully available if you use the generic Git option. If you want to load binaries, then you have JVariant factory or any HTTP server that accepts post and put. If you want to create platform-specific packages, there's Homebrew for OSX and Linux, Chocolate for Windows with Docker images. You can also package with J-Bank, because J-Bank supports some sort of launching jar files or other sorts of binaries. The scope is for Windows, as the command is for the three major platforms, RSNAP is for Linux. And in terms of communication channels, well, there you have it. There is definitely more than one. And there's likely that if your team decides to use any of these communication channels, then you can simply ping them and send in an announcement. Now, how did you launch the tool? There are a few ways. If you are on OSX or Mac, well, you can install it from SDKman, or you can use J-Bank to launch the latest version, or you can install it from Homebrew, or you can go to the release page of the project and download a CIP file. There are two versions, one that expects you to have a Java runtime that matches the expectations, in this case it's Java 8, or the standalone version, which is a cross-platform J-Link Java runtime created with Java Lisa. So you don't need any Java in your environment. It comes with Java Lisa. For Linux, almost the same instructions, you can use SDKman, J-Bank, or download are released. Notice that there is a secondary standalone version with Linux muscle platform. This is useful when running on Alpine Linux, because the first standalone works with any JBM, well, actually it's a particular JBM that runs on JLBC, whereas the other one runs compiled with muscle. I don't win those, almost the same options, but you also have a scope, right? So you might be wondering, well, these options are maybe very similar. The JREleaser happens to be a CLI tool, which is written in Java, it's just like any other Java project that you would like to release. Does JREleaser use JREleaser to release itself? Yes, since the first release. So all these options that are available to you have been crafted using a model published by a previous version of JREleaser. If you want, you can also grab the CLI using an executable jar. You can download it from the release page, or you can use this simple script. Just run it with Java 10, or actually you need Java 11, I believe, but this feature is available since Java 10 is the search launch from source file. And what these things do, we'll just download the Java jar file, and then from there you can execute the jar file passing any additional commands. We also have Docker images, they are the latest numbers. The Slim version, this is for based on Ubuntu, and the Alpine version is based on Linux Outline. Now, these Docker images do not support packaging for snack craft and chocolate snack craft, because you require additional tools and additional settings in the image, which we haven't done yet, and chocolate requires a Windows image. So, well, no dice there. You can run it many ways. You can run it from the command line as a CLI tool, or you can run it as a Maven plugin, as an Ant task, or as a Gradle plugin. We also support running in CI-CD environment. So, you can run it locally if you want to, but if you happen to run releases on any of these 14 different options, then you can use JR Lisa. We have native integration for GitHub Actions, because we have a GitHub Action for JR Lisa. The others might either rely on the Docker images or downloading the jar file and executing it as is. So, we have guides in the documentation telling you how you can use any of these services. So, from your point of view, the inputs that you supply to JR Lisa are the following ones. It's a C file or a tar ball that is created either using, again, Maven, Ant, Gradle, or you can do it by hand. These are typically distributions that contain a launcher script and all the jar files needed to launch the application. You can also pass in a FAT jar or an Uber jar that is executable. You can pass in a J-link distribution that you created by any other means, or using the assembly block for JR Lisa. Grad native image also created using the assembly block, or using the Maven plugin, or the Gradle plugin, or anything else, or their means. And finally, even though the project started as something for supporting Java projects, we also support native packages and native executables. Native packages created with J-package, or native executables that are created from any other source file that is not Java. So, if you're creating a binary with C, C++, Rust, JavaScript, you name it. You can use JR Lisa. If you happen to use Go, then I will certainly recommend you to keep using Go, release it because that provides tighter integration with the Go language. But for any other kind of project, JR Lisa should be fine. Okay. So, that's enough of the theory. Now, let's get into the exciting part, which is the demo, which hopefully will work and nothing will break today. So, here we go. Let's show the turnout. So, before I get that, I have this simple project. It's a Java project that is based on Maven. We have a JR Lisa model right here. And the only thing that this thing does is it's a simple CLI that outputs, I think it's either Hello World or it outputs 42. We can have a quick look into it. What does this thing do? It says Hello and something. Okay. Not very exciting, but it's a Java application. Right. So, let's go here. Oops. You didn't see that. So, let's do a clean so that there's nothing out there. Right. Okay. So, what I'm going to do now is build the application and I have set up the application such that it creates C files and a target C with some distribution. Now, this is just regular Maven. You see the POM file here. It was just gap coordinates. So, metadata. This is standard, blah, blah, blah. We start to see other plugins. If I want to execute the application from the build, that's fine. I make it executable because there's the jar plugin. Then I create a distribution using the app assembler. This is the one that creates the launcher script and puts all the dependencies. In this case, the application doesn't have any, but if you add, we'll put everything into one directory called live. And then the assembly plugin, this is the one that creates the C file and the target file. And that's the only thing that I do. Okay. So, if I show you again here the Git repository, I have no tags and I have no releases. So, here's the first thing that I'm going to do. I have a binary. And I want to create a Git release without publishing any files. Would you notice what's going to happen? I can use jreleaser if I already installed it. How can I install it? Remember, I can use it as you came in. So, let's list the different versions of jreleaser. I'm going to use version zero six, which is the latest release. We can verify that I have the latest version like that. It is correct. So, now I can say jreleaser release and pass in an additional configuration that says autoconfig. This will take information from the project itself from Git, from the Git directory and the basic metadata. And the next thing I need to do is tell it what version I want to use if I remember correctly. Should be this one. Okay. So, now jreleaser starts to work. It says autoconfigure is on. Perfect. So, metadata generates a change log. Then there are no files configured for check summing nor signing nor uploading, but releases to this particular URL. Now, if I go back here and do a refresh, now I have a tag and I have a release. Nice. I noticed that this is a very trivial change log based on all the commits. And because I have set up my personal token and signatures, this is verified. Perfect. Well, this is very plain, right? Let's move now into the model. The model I made it external, but it could have been using Naven. So, there's some duplication perhaps for Naven. There is this most information is found in the POM file. Okay. Then I have some information based on the actual release. So, I'm going to release to GitHub. If there's any matching release without a particular tag, I'm going to write it. I want to sign it. When I create a release, I'm going to pass in a discussion and I'm going to give information for formatting the change log. So, this will come up later. I'm also going to sign artifacts. I have that configuration with PGP. I want to, not for now, I don't want to configure homebrew, but notice that just packaging homebrew with all the defaults is as easy as doing that. So, I'm going to disable homebrew for now. And then these are the distributions. These are the binaries that I want to publish. You can pass in the actual name or use some sort of placeholders. These look like moustache templates. You might have find them using on the front end. But we also use that for net. So, there's a C file and a tar file. And finally, I'm going to announce two different channels. I'm going to announce to my Discord channel and I'm going to announce to a solid forum. Now, there is no information about Discord right here explicit because I'm using a web hook. Anyone that has access to the web hook will be able to publish to my Discord server. So, I have that information stored in a secret spot that Gerreleaser can understand, which is you can see it right here. There are many configuration formats. It could be Jamo, Tomo, Jason. I decided to go with Tomo. And now notice what happens. I'm going to, instead of saying autoconfig, I'm going to say Gerreleaser, Release. And given that I already have the model, this should create a new release. Let's do it. Now, as a result, autoconfiguration is no longer turned on. There is some metadata. Check sums, the files, signs, the files, and then creates the release saying there are a bunch of assets now being added. And finally, I go out here and do a refresh. And notice that the change to it looks much, much better. And here are all the assets, the binaries, the signature, and the checksums. If I go back here, there's attack, and here go into discussions. There is the discussion that was just created. This all happens automatically. And you may notice I am affecting a remote repository on my local environment. Of course, you can use GitHub Actions. So if you go here and CLI Release, this is just like any other GitHub action that takes one additional input so I can say, I want to release version 1.0.0 or 2.0.0, any version I want to as long as it matches what Maven creates. Check out, cache Maven, set of Java, build the artifacts. And then I need to use Java 11 to run the action and then just pass in the release action and an additional set of secrets. And this makes the magic happen. One more thing. I'm going to announce now that I made a release. This should pause to discord and to sullit. So we see these two things because those were the things that were configured in the model. So now that I go here into my discord channel, I have this announcement that it's been just today Swiss time. I can go into my sullit forum and I have this announcement that is also posted right now Swiss time. And if I click on that tag, of course, it's going to move me to the release that is available on GitHub. Now again, you can do this locally or you can do this remotely on CI. And the next thing is if I wanted to release these to GitLab or GitHub, the only thing that I need to do if I want to be explicit is this and have this project as a repository on GitLab matching, well, this is just documentation, but if you want to be really, really explicit will be that. And the rest of the model is identical. It's exactly the same. It just works. And again, you can run manually or you can run it on CI. That is the advantage of using a tool like this that it automates lots and lots of things. There are a series of projects out there that make use of Jerry Lisa. Perhaps the one that I would like to showcase today is called Casey Cuddle. It's a KafkaConnect CLI built with Quarkus that produces native image executables with Quarkus support. What we want to do is publish the three binaries for Windows, Linux and Mac using Jerry Lisa. So here is, there is a tag. It's an early access with just one change. And if we look into the assets, there are three binaries, two C files and one RGC. These are created using Quarkus. This project uses Maven. There is no Jerry Lisa Jammel file because this project uses the Jerry Lisa Maven plugin. So this is just regular Quarkus stuff. The important bit will be here at the end. Here is the red Jerry Lisa Maven plugin, latest version. And we list the different artifacts. We need the RGC, the C file and the other C file for OSX. And this, given that we're building binaries, we use Github Actions with this workflow to create the different binaries matching the different OSX Windows organics. That creates three different binaries. And this release job collects all the binaries and invokes their release action. Well, actually invokes the release goal from the Maven plugin. So you see there are different ways that you can invoke this and whether you are remote or not. One more thing that I would like to showcase before I go back to the slides will be the website. So the website contains all the information that is needed for you to understand how the tool came to be and how it can be used. What are the different types of distributions? So these are the inputs that you provide. Configuring all the different blocks. Let me show you their release block, which is here for Github, which is right here. So this is pretty much what we saw earlier, the Jammel format. But if you don't like Jammel, that's okay. You can use Tommel or JSON, or use the Maven DSL, or use the Gradle DSL. Every single snippet, it's provided with five different options. You want to know what are the different commands for the CLI? There they are. So for example, there is the full release, which shows you all the different options. Or you want to see the Maven plugin, well, there you are. And there it is again, full release, the different options, and Gradle and everything else. The guides for all the different CLI elements. There you go. And so many other things, right? And finally, some examples, showcasing Jerelease's release itself. So this is a copy of the release that Jerelease uses to create all the different options, such as, well, here's the change log. So that's fine. And here we have assembly for the cross-platform J-link. So that's a bunch of instructions that uses JDEPS and J-link. Or the binaries that were created using Gradle because this project uses Gradle, the end tasks, the CLI, and again, Docker images that we put into Docker Hub. So it's just one model. And this creates a lot of different distributions and binaries that your users can consume. All right. So let's go back to the slides. And, Reyes, I think you have a few questions as well. Okay. So let me check in the chat. Very nice just to note, custom code, a plugin to release or announce to internal channels. I thought about it, but that would require having explicit support in DSL if you want to use a name it channel. So we have plenty of communication channels, and we also support the generic webhooks. If the project or the other communication channel that you want to use will fit with a webhook, then off you go. But if it does not, then we'll have to figure something out. All right. And we'll have to think about how we can support custom channels without having to add a specific name for it. How configurable are the webhook payloads? They are configurable. So if I go back here into, let's stop the slides. So that's the advantage of having the documentation here is that if you go into announce and say custom webhook, then you can pass in the message as is. And notice that it also supports those placeholders. Or you can pass in a file, a message template that can contain much more information. And it also supports these templates. And pretty much most of the announcement tools that we have here supported this announcement service will either support this or the other. So you can definitely configure them. And where was the last message on the chat? Which is, is the Github plugin compatible with Github Enterprise? Yes. Not only with Github Enterprise, but also Github Enterprise. As long as it's Github or Github, it supports that protocol, off you go. You only have to change one thing, which is go here into release and Github. And make sure that you define the host, which by default is Github.com. And you also define the API endpoint that has to match your Github Enterprise endpoint. The same deal will happen with Github. You have to configure the host and the endpoint. So yes, we support those things. All right. Any other more questions? We'll see. Okay. So what's in the future? The current version is 060. We have a lot low numbers just because I want, I don't want to promise the 1.0 so quickly, but it looks like we are getting there very, very fast. I mentioned that we support generic Gith services. It might make sense to support explicitly Bitbucket, Azure, AWS. We'll see that in the future. Additional upload services, I mentioned JVR Artifactory and HTTP, but it might make sense to publish binaries to Cloud buckets, such as Amazon S3 or Azure or Oracle Cloud. You name it, any of those Cloud services. And just like we do with the assembly step that we can create JLink images and native images with Cloud, we might be able to also create J package binaries. You can do this outside of JReleaser, maybe manually, you name it. But if we do it with the assembly, then we can reuse some of the metadata that is common for these binaries, these packages, and for the project itself. This is still ongoing. And I think that once we have this support, we might be able to publish version 1.0.0. One thing that I did not probably forgot to mention is that if we look into JReleaser's build, what is it? We go into Github, JReleaser. It says that it has seven releases. So all the final releases for one of two six, but also has one thing that is called a rolling release or an early access release, where it said, there you go. This early access release is published every time we make a commit to the main branch and reuses the same release model. So the only thing that it changes is the version number and the tag and mark this thing as a prior release. But the way that this thing is built is exactly the same as how a final release is built. It's just a tiny change in the configuration. So that allows you, and in this case also JReleaser, to publish early binaries whenever you want it. So even though we have not released version 0.7, you can go here and download any of these binaries matching your expectations and then use the latest version of JReleaser. The Github action is also configured to pull in the latest version if you have to configure that or the early access version or the specific version. So it's up to you to pick which version you want to use. Okay. So some resources, closing remarks. Again, the website for the project is jreleaser.org and the project is hosted on Github. It's fully open source. And if you would like to contribute, that's fine. We will certainly welcome your contributions. You had an idea of a service that is missing integration, such as that question for any other internal communication channel. Please open a discussion channel and maybe open an issue or in the base case or if you want to send us a poll request. And we see how we can integrate that particular contribution. So everything that we have seen today is open source and you have not contributed to open source before is easy. You find a problem with anything that we saw today or any other open source project that you use in your daily work, file a ticket. That's it. You don't have to send code. Just file a ticket, let the people at the other side know that there is a missing feature or there is a bug or there is something else that's probably not working properly with the project. If you have the time and the passion, sure, sell some code, but it's not as strict required. So with that, I thank you very much. And I think that's everything that I wanted to show today. Of course, there are many things that I would like to show, given that we have a passion for this tool. But we are pretty much almost on time. I think we have like five more minutes for questions in case anyone else has something else that we'd like to ask. Hi, Andres. Yeah. Can you actually give us a bit of information on Chocolati also? I've never heard about it. I was quite curious as to how Chocolati and J.D.D. also works together. So how often J.D.D. works together with each other too? Can you repeat that, please? Chocolati you were mentioning about, right? Chocolati, yes. Right. So right now, Jerry Lisa can build, well, it creates the manifests that you require for Chocolati. But it does not yet invoke the Chocolati binary that creates the final package and pushes it to the Chocolati repository. The reason being is that you will need to run the Chocolati binary on a Windows machine. Now, we know what it needs to be done, but we have not done so yet. But there is an alternative. You can generate the manifest and the companion files with Jerry Lisa using the templates. Publish that to, let's say, that you have hosted your project on Github. You publish that to a Github repository and use Github actions on a Windows runner to invoke the Chocolati binary. So this is a little bit more work on your side because you need to configure the Github action. In the future, we will make sure that this will be able to run within Jerry Lisa. This workaround, by the way, is what J.Bank does. J.Bank now also uses Jerry Lisa to release itself. Currently, it supports Chocolati, and it uses a separate Github repository to do the same. Now, the advantage is that Jerry Lisa can create that repository and update the Chocolati repository every time that you push a new release. Yes, thanks, Andres. My pleasure. I guess Akush has shared. If you look here into the Jerry Lisa organization, you see different repositories. The repository that contains all the Docker files and the Snapcraft files and the Scoop manifest and the Homebrew manifest, all these repositories were created by Jerry Lisa itself. And every time that we push a release, a final release, then the contents of these repositories get updated. And if these repositories happen to have additional workflows, then those workflows will trigger as well. So you can set up all your build pipeline the way that you want it. Okay, so let me reply that, well, I'm quite excited about this tool. I have achieved my goal of publishing binaries for a JavaScript application and a few other things. And now more people are discovering this tool and making sure that they can invoke it in different ways. Again, you can just invoke a full release or there are other projects where they say, I will create the Git release on my own. But I want to publish to Homebrew and I want to have Chexons, so they use Jerry Lisa. Or is the other way around. I want to create the Git release, and I don't want to take the hassle of using Github Actions. And I don't care about the other binaries. I just need the release. And there are others that say I want to create the release and the announcement. But I don't need any binaries. So you can have the combination of different options as you need it. This is not a one size fits all tool. It's a highly configurable, very flexible tool. So it's up to you if you want to pick it up to decide how you want to make it work. Excellent. Thanks a lot, Andres. So that was really cool and lots of good information. I think Jerome next to me is finalizing. I can try some. You want to show it? I will try. Normally, if the miracle of technology is working, I would be able to not do it today. So maybe we just show it. So we want to send you there. That's your question. Thanks. Yeah, we want to send it to the Meetup group and we want to email it to you personally. Yeah, thanks a lot for coming. It's very nice to have you again, Andres. And yes, without waiting, we're going to move to our second speaker who is Dimitri Chouico. And yeah, Dimitri is one of the JVM gurus. He used to work at Oracle on the JVM before. Now he's a performance architect at Bellsoft, which is one of the most active companies on OpenJDK. So hi, Dimitri. So thanks a lot for joining me. Hi. And yes, we have the pros and jewels Dimitri. So yeah, thanks a lot for coming. And yes, tell us more about yourself and what you'll talk about. All right. So you introduced myself very well. Thanks again. We are going to talk about some grail we are going to chase. And what is it nowadays? We are trying to find effectiveness without making much efforts. We're trying to make our application, our services, our products, make them perform best or test better. And surprisingly, it can be reached relatively easily by some modern tools that we have now. And what I do, I participate in development of one of greatest products in IT history, OpenJDK, which I guess you all use. And our company, this is some binary called America JDK. And it's great to hear what Anders just did, what he just presented in the talk, because we use many of the mentioned channels to distribute the JDK. It's great that we have such distribution channels, platforms where we can provide software builds and SDKs as well. I mean, SDK men, same chocolate, all them. So it works together very well. And yeah, my colleagues do a great job of contributing to OpenJDK, and that's what we do daily. If we talk about effectiveness, modern standard of the factor is usage of containers, or at least virtual machines, but we know that we all migrate to containers. And we try to make them more effective. My previous talks were about how OpenJDK handled this new reality, and now it started to work very well in containers by default out of the box. We just take it and it works great. Typically, if you look at some container that we produce manually or some tool does it for us, it is a layered one. So we have layers to make our updates faster, because we can update only layers that changed. So of course, it's layered with some voice libraries, some packages that we need to run the cherry. We need then the cherry itself. Maybe we need some other voice packages for our application. That's the second part. And then, of course, Java libraries, all the classical stuff, some maybe framework. And then the tiny part, the tip of the iceberg, where our business logic lives. Here's another picture. What happens if we create native images? Sometimes, they may be even based on the scratch image, because the nature of native image seems that we put everything together and we can link some additional libraries. So it's basically simpler, but we cannot split it to layers. Otherwise, we will lose in performance. Why? Because we'll have dynamic dependencies. And for example, such thing as inlining won't be possible. So the nature of static compilation, if we compile two parts statically distinct from each other, then we don't align. We just combine them dynamically. I will mention a couple of examples based on spring, both. And first, we can go to, for example, spring initializer and create a simple service. And as I mentioned, the part that actually performs is a point for some customization for our core. It's very small. If we assemble a thin jar and libraries, then libraries will take approximately the same amount of disk space as a fudger, like 37 megabytes in this example. And our logic will take like three kilobytes. You see, it's a very small tip of an iceberg. This is just a regular service. Nothing unusual. We just need some database connection. We'll use spring boot on bulk. It's very simple. And about a year ago, I noticed two interesting polls in one of the conferences. And I think it is still a valid picture, except the share of cloud native build packs usage. My guess is that it is growing. I think we'll definitely repeat such polls this year. It's very interesting what has changed. But for now, that would be the major difference. And you see, many of us still create Dockerfiles manually, still describe how our containers, what's really out there. And surprisingly, the share of classical deployments is still very big. I mean, bare metal, virtual machines, wire deployments, it's still huge. But cloud native build packs is a growing point here. If I talk about Bayesian variant images, I will switch between the terms. So for us, we'll create JDKs. The Bayse image is an image that is capable of running the sum job program. And that JDK can be embedded into that image in a different way. Some obvious step is to install it as a package from your underlying operating system layer. Sometimes that may be a package that is acquired from some external repositories. So we first plug in a repository and then you install a package from that repository. That sometimes has some advantages. And that may be a binary installation. In all the cases, it would be good to be sure in the compatibility. So something you install that it will work well. It sounds obvious, but we'll look at a few examples where this assumption breaks. So let's finally try something. Let's try some image. Okay, I need OpenJDK. I get it. But for example, my network, that's my home network. It's rather fast. But I have to wait for a half of a minute to get the image. That's a lot to me. So I can show a couple of slides during the time. That's not fast. Why? Because I really transfer a lot of data. I wonder it can be even estimated from the time that you saw, you know, the speed of the network. So then this image is uncompressed on disk. It takes more than half of a gigabyte. Well, why? I only need Java to run some Java programs. Is that right? No, I don't think so. And especially it is not right that I have a lot of machines. And some actions may be cheap. Like network transfer may be like free in some clouds if you don't cross the region size. But if you do cross that, or have some other penalty, like for example, you share your machine and your disk is already full and you get additional disk, you have to pay for it. That may be slow. That may be expensive. And you know, if I deploy something for not so many machines, I have quarter of terabyte flying around. It doesn't sound right. It doesn't sound right. So here, obviously, smaller containers, if we deploy in a classical way, if we use JVMs and we need smaller containers to JVMs, they will help us. Well, we can go and search for some small container and we will find few ones, probably many ones. So how to choose between that alternatives? How to compare them? Well, we can compare size, right? Like take two options and you see one option with Java 8 is smaller than another. And its difference is quite impressive. But we took the latest version so that containers and the smaller one, it doesn't have the latest version of Java. Moreover, it contains the version of Java that is about a year old. That means all security updates and some features are missing. And that may be really critical. For example, I need to enable Flight Recorder. That is for a long time, it is an open JDK. It's available for us. I like to use it. And I cannot enable it in some container images because they contain the version of JDK that is old that JFR is just not there. From another hand, we can take what frameworks offer for free. So they contain plugins, for example, for Maven that build containers for us. And you just issue Maven and Gradle command line and you get a container in your local repository after that. And what's even better, it's already layered. So you have separate layers for your JDK, for your application, and even your application is split into layers with libraries. So here the example is Springboard. And we just issue a build image command. And now the very same command can be used to build image with JVM and to build a container image with a native image of your application. So how to switch between them? Typically, if we use some part of the .pom.xml file derived from what samples offer us and archetypes, there's a property, actually, environment variable that you can switch to and false. That says, do a built native image or do a built-in container with JVM. So we just used out-of-the-box thing and got the container that's not half of the gigabyte, but just less than 300 megabytes. Good, isn't it? We just saved a lot of disk space, and we saved full time. Inside, every such image contains an OS layer, as I mentioned. And there are multiple options. There are many options which OS layer to choose, especially if you build it yourself. You pick some OS image or you create it. And their size, for example, is very different. And they even are based on the different C libraries. And they have different package managers. And I guess it's good also to have some shell to perform some diagnostic, some maybe control to run additional scripts. And there's one special one, Alpine Linux, that is extremely small. And it contains standard C library, package manager, and content shell. And it's even smaller than something called Distralis, which is a small thing created from a real OS distribution by cutting off package manager and shell. So to run JVM on such small and special OS, we need to port it there. And it has been done with JAP386. And it was maintained in Project Portola in OpenJDK, where our company participated, and also it has been started by Oracle. And now you have it in JDK 16. What it means is that if you look at OpenJDK repository, if you look at the main branch, it's there. But that doesn't mean you cannot have it as a binary for earlier JDKs. So a few companies released binaries for a few releases. And those binaries and containers are much smaller, obviously, as you saw with base OS or their size. And the same difference is for resulting container. And if you pull that, it doesn't take half of a minute, it takes just a few seconds. So you say BAMs, and you have OpenJDK on your machine, which you can experiment with, and you can create container based on that. And it's cool. If you have CI and you provision new machines, it's instant. But wait. I show, of course, some examples of this, but it's not the only one, not the only container image that uses alpine, for example. It uses alpine muscle, but you see, for example, JDK8, and look at its size again. You see, there are options. Why there is such a big difference? Why America is not smallest? Is there a problem? Well, the technique of making the JDK even smaller is obvious. It is to compress some jars that libraries, standard libraries in JDK. And for JDK8, those are not modules, not jmod files. They are really jars, so you can compress it. Well, and you will have an impression difference in the uncompressed size. But first of all, you will have startup penalty, because you have to uncompress that, then you read the classes from the jars. And this startup penalty is solvable, but still you will have worse wire size. Then you transfer and compress already compressed jars. You will have worse and larger size, and then the JDK, the uncompressed jars that has been compressed once. And then you transfer JDK layer, the compression is applied. Some other interesting options. Well, many of us love async profiler for a real fine-grained profiling of your applications, allocations, CPU profiling. So with that easy, you can tune your container to support it. Then you try to profile something. You run your Java application, you get the process ID, and you connect your profiler, and it just shows you nothing. It basically shows that many things happen in JVM, but it doesn't tell you what really happens. And if you take the distribution that has the box symbols, you actually know that, for example, you have a warmup phase and your C2 compiler is working here. And it's not a big deal. You just need to like 40,000 symbols. They don't take much space. You just need to be careful about how your JDK is prepared for profiling. So as I mentioned, JDK 8 is available, while the code of protocol approach has been merged on the timeline of JDK 16. As well as JDK 11 builds are available in multiple distros. You can just try it. And the same is for ARM. If you have an ARM server or some other kind of machine to try, like my book, for example, go on and take your native ARM binary. What about OpenItself? It also contains OpenDTK package. But distros doesn't care that much about building and making OpenJDK packages polished as JDK vendors. It's funny, but you can, for example, install OpenJDK there and try to use a JCMD command and it just won't work. Well, it's there. You can try and invoke it using full path and we'll make something basic, try to figure out what's the uptime of some running JVM. And instead we'll have threadnump. Well, because something was not done properly during the build process. So your application basically works. But this diagnostic option just doesn't work. Why? Well, just take the right base image and everything works out of the box. You have JCMD and your VM uptime command gives you what's expected. We all know that using public Docker registry sometimes and especially for the past year, it became, there are some pitfalls. It's fast. That's the great advantage. It's free. But there are limits. And you actually have a different option. First, you can make a repository inside your organization network that will act as a proxy. Or you even may use local repository for everything. Just if you started from starting, for example, from scratch and you don't need other images, well, that's great. Or you can from time to time pull some layers, images from the public Docker hub. Or you can connect to private repositories. Use them the same way. That's the early access option. You can go there or you may not go if you wish. The trusted registry is basically, it works very similar to public Docker hub. You just need a credential that's in that way thing. And then you get some nice additions. For example, in our case, we provide early access binders there. And commercial customers, they get binders built especially for them. There are cases, for example, you need a hotfix. And this is a channel of distribution, a private channel to deliver a prepared base image with fixed and tested JDK to some customer. And we also experimented with early access builds by adding some optimizations there and providing them using the same channel. Like, for example, extra size decrease that we reached the latest releases, especially for JDK 11. But not just that. Also some latency improvements. And the thing that I like to show most, it's decreased memory footprint. So when you take somewhere well-known application and start it and do nothing, it's a very simple test. It's pet clinic, no matter which flavor of it. And we have optimized JDK. This is the JDK 11. There's some extra back ports. Good ones that make it consume less memory. So you see the footprint decreased more than 150 megabytes. And we just did nothing. We just changed the base image for our container. And it started to consume much less memory. So as I mentioned, there are options to choose from. Then we built our container image. It may be a JVM-based image or it may be a native image container. Native image has its own advantages and disadvantages. Like, for example, diagnostic tools that we used to. They are not available. We need a slightly different approach for diagnostics, longer build times, close world assumption. We need sometimes special versions for different components that we have as a dependencies. So it's sometimes complicated. But we have advantages such as smaller container size. And we have, it is a single binary. But if we choose traditional JVM, we also have options. How do we work the voice layer? Which package manager do we prefer? Is muscle fine for us? Not just JDBC, but muscle. If JDBC is a must, then again, which package manager do we prefer? What distro flavor is best for us? And if we continue to talk about native images and static compilation, there was an attempt to bring static compilation to help application startup in JDK. But now this feature is being removed from JDK. It will be removed from JDK 17, I guess. I mean, the feature called. So there are no more new growl compiler drops to open JDK source. So if you look at open JD GitHub, the growl code, growl module is still there, but it's not updated. The part that is being developed is JVM CI because it's still used by growl VM. It's still used by other tools. So the interface is there. It's still experimental, but it's being developed. So that's an interface for plugin in the growl. And then we can think of different growl VM assemblies. There are assemblies by Oracle, basically free growl VM community edition, available for a couple of platforms, and also a growl VM enterprise edition with the same license as JVC. And it contains additional optimizations. But you can try, evaluate it, and decide if you really need that for your production. And there's one more interesting assembly that is based not on the growl VM, a special VM assembly, but it's based on the Berger JDK. And we provided to cover that niche of native image and native image containers. Because we believe that the variety of choices that I've shown you, it's better to have it covered with support from JDK and compiler vendor. And we also see that there are platforms that many users are interested in, like working on muscle, working on arm, and we still make it possible to use extra languages for native images using that tool. So what's the difference? We cannot use them dynamically in a JVM mode, but we use them in a native image. So we made some efforts in growl VM project to make Alpine Linux support more production ready, more complete. That was for extra languages, for running the compilation process on the Alpine Linux and usage and running the result in native image on the Alpine Linux platform. So it's very easy to take that tool, just go to the download page and get it. And let's discuss some other tiny example, which is again, you see, if we built JAR for classical JVM, the Asperg-T part is very small, the library's part is still huge. So it takes like 17 megabytes if it's a FUDJAR, but we can enable support for native images. In this case, it's spring. We'll need a few components. We will need a special plugin that performs some actions before running in your applications. So this is a Spring IoT ML plugin, but IoT here doesn't mean the compilation. It really means some code generation and generation of configuration, everything that can and must be done ahead of time before running your native image compiler. You will also need Spring native plugin to handle all the dark magic, taking away all the complexity of turning and working other plugins and turning your code into native image. The optional dependency here is a dependency for manually running plugin from RALVM team. You can use only that. For example, in your some simple Java projects, you can enable this plugin and turn them into native images. But the complex ones, like something that's based on IFC containers or dynamic proxies or whatever, which is not trivial for native image. And I guess that's anything rather complex or complex enough to work with databases. Something with a lot of code. So you can use, you have to use more sophisticated configuration. And that's handled behind the scenes with some custom plugins, but you still can invoke the final stage using the original native image maybe plugin. And you can also specify an exact version of it here. And in my example, I declared some profile to work there. So flexibility here is that we can invoke that profile optionally. And as I mentioned, we can also plug in built packs, which will ease all the container work for us. And if you now state that we will create native images by providing such a property, and we invoke the same spring build, build image command, and we get an image, the native container image, the native image of the application as a result. But for flexible build, we can also use extra options. We can control which exact version of native image to how we're using. Like here, we take some exact version of Librarian native image kit. And we can use, for example, Alpine Linux. So here we tune the Alpine environment for the build and we create a resultant image that will work also in Alpine environment. We can just run it. And this environment is super tiny. So we don't have that, you know, 100 megabytes plus 37 megabytes. We have only seven plus 5.6. And the resultant image starts in 120 for the second. It is much faster than a blink of an eye. That's the great option for us. We can make our application to start that fast and to take that tiny container space. Well, sometimes native image is a complex. It takes long to compile it, but we have great advantages. One of them is, again, a footprint. So you remember the saved a lot of memory by using extra optimizations in the AVM. But if we switch to native image, we save it even more. We did nothing with our code. We just changed the configuration, the way how we built the resultant artifact. And it takes slightly over 100 megabytes of memory. Super small one. Yeah, you can just try it. Or you can try Spring Native. You heard the announcement, but now the American e-case, the default assembly for Spring Native, if we use built packs, built containers. Thank you. I will switch to questions now. Okay. We have any questions? We don't have questions in chat. Yeah. Please ask. Maybe Dimitri, I have a question. How is the process for the contributions to OpenJDK? Is it like completely open source, like an enormous open source project? Or is it like you guys do much requests and all that kind of stuff? Or it's a bit different? It was more different than regular. So every project has its way of development. Now it's all on GitHub. There is additional tooling around that. But you can come with a pull request. One thing that you will need is a special agreement. It's called OCA, Oracle Contributors Agreement, signed by a company or by an individual. Okay. You work in the very same way as all others in the community. It's really not complex. If you wish to contribute, you can sign the OCA and go to the pull request. Or you can send your patch to a mailing list. That's also fine. Thank you. I think we have one more question from Anbu. I see there's two versions of Nick Core and Nick Standard. Can you share a difference? Also, the recent announcement and the theme was Pink Native. What to expect in the future. Thank you. Yeah. That's a great question. I like to mention that announcement. Of course, Nick Core is a version instantly prepared for creating native images from your Java programs. It's not magic. It's the version with a native image to install and other tooling stripped off. So it's slightly optimized to be ready for creating native images from Java programs out of the box. You can take standard version, standard package and install native image tool there in a very regular way for GraphVM derived things. You just type GU, install native image, and it's there. Except everything is downloaded from the same binary repositories as Nick itself. What to expect in the future. We have more thoughts on how to improve experience with Alpine Linux. It sounds very interesting to many users and we do like it. We started experiments a few years ago with JVM and we like to continue that. Some other tools around JVM, but they're not related directly to Spring. We have the Verica administration center. But for Spring Native, we expect some bugs. That's not just something about having our binary by default in this great framework. But we also back at the support. So if something breaks in some company's environment, we'll fix that. And we have more interesting thoughts about using native images, for example, for UI development, creating some binders. So again, I like very much how hundreds uses JavaFX. So that's also an interesting direction here. Yeah, thanks very much, Dimitri. I think we're reaching the picture in time. So yeah, that's it. It will be more visible at one point. Thanks very much, Dimitri, for joining. Thanks, everyone. It has been a while and we hope to see you next time probably in a couple of months. You have our next event. Thanks. Thank you. Thanks, Dimitri. Thanks, Andreas. Thanks, everyone. Thank you. Have a good night.