Unleashing Native Imaging Power in GraalVM
In this insightful discussion between Bert Jan Schrijver and Alina Yurenko, the focus revolves around demystifying GraalVM and its dynamic compilation challenges. Bert initiates the conversation by delving into the intricacies of JIT compilation and its adaptability during runtime, prompting Alina to elucidate on GraalVM's distinctive approach through ahead-of-time compilation. They explore the nuanced concept of profile-guided optimizations, allowing developers to glean insights into their application's future runtime behavior. Alina emphasizes the significant benefits of native image, such as enhanced startup times and resource efficiency, shedding light on its impact on microservices and serverless applications. The dialogue seamlessly transitions to the security advantages of native image, underscoring the reduction in attack surfaces and the meticulous control it offers over an application's functionality. Ultimately, the conversation provides a comprehensive overview of GraalVM's capabilities, making it a valuable resource for developers seeking to harness the power of native image compilation.
About the experts
Alina Yurenko ( expert )
Developer advocate for GraalVM at Oracle Labs
Bert Jan Schrijver ( interviewer )
JavaOne Rockstar & Champion, NLJUG leader & CTO at OpenValue
Read further
Introduction
In this insightful discussion between Bert Jan Schrijver and Alina Yurenko, the focus revolves around demystifying GraalVM and its dynamic compilation challenges. Bert initiates the conversation by delving into the intricacies of JIT compilation and its adaptability during runtime, prompting Alina to elucidate on GraalVM's distinctive approach through ahead-of-time compilation. They explore the nuanced concept of profile-guided optimizations, allowing developers to glean insights into their application's future runtime behavior. Alina emphasizes the significant benefits of native image, such as enhanced startup times and resource efficiency, shedding light on its impact on microservices and serverless applications. The dialogue seamlessly transitions to the security advantages of native image, underscoring the reduction in attack surfaces and the meticulous control it offers over an application's functionality. Ultimately, the conversation provides a comprehensive overview of GraalVM's capabilities, making it a valuable resource for developers seeking to harness the power of native image compilation.
What is GraalVM?
Bert Jan Schrijver: Hello, and welcome to another episode of "GOTO Unscripted." My name is Bert Jan Schrijver. I'm CTO at OpenValue. And I'm here at GOTO Amsterdam, together with Alina Yurenko.
Alina Yurenko: Hi, everyone. My name is Alina Yurenko, and I work as a developer advocate for GraalVM at Oracle Labs.
Bert Jan Schrijver: So, let's talk about GraalVM, Alina Yurenko. Well, what is Graal, what is GraalVM? Can you explain it in maybe 10 sentences?
Alina Yurenko: Ten sentences? Okay. That will be challenging because GraalVM is so many things, and in a way, it's a nice challenge to have, right? But also, then, it makes it kind of hard to explain to people what is it. But I would divide it into three parts. So, one is GraalVM is a high-performance JDK. So, it's a JDK like any other JDK you might be using, like OpenJDK. It has the same HotSpot VM, but we replaced the compiler with our own Graal compiler. So, that's one part of the story, is that you can use it as a JDK, to run your applications with the java command, as you normally do. Then there is another big part of the story, and that is native image, and that is this ahead-of-time compilation of Java applications, that produces native executables that can run without a JVM. So, that is also GraalVM. And last but not least, people also call it a polyglot VM, because, in addition to Java, and all those traditional JVM languages, Scala, Kotlin, it can also run JavaScript, Python, or even your custom language. So, three things, but in a nutshell, it's a high-performance virtual machine for many languages.
Benefits of Using GraalVM
Bert Jan Schrijver: Okay. Well, so, I've been doing Java development for a while. I know where I can get my JDK or JVM. Why should I use GraalVM instead of another VM?
Alina Yurenko: There can be so many reasons why you could be using GraalVM instead of any other VM. So, one thing is that you can use it as a JDK, right? So, just run your code on a JVM with just-in-time compilation. The reason to do so is that workloads, some workloads, many of them, will see speed-up just by switching to GraalVM as a JDK because we have this new compiler. It cannot give you a specific number for the speed-up that any random application in the world will see, because it highly depends on what the application does, what dependencies it's using, how it's written, etc. But I do recommend always at least checking out GraalVM as a JDK. So, that's one reason to use it over any other JDK. But I think the area where we see a lot of interest is a native image, and the way to build your Java applications as a native executable, that no longer needs JVM to run. And the reason to do so, I mean, sometimes people ask us, but why give up JVM, because it gives us so many benefits? And it does. But also, it's just another way to deploy and build your Java applications. So, maybe if you care a bit more about startup, memory usage, about these kinds of things, then the native image would be a way to go.
Bert Jan Schrijver: Well, I have a lot of questions about native images, but...
Alina Yurenko: I had no doubt.
Bert Jan Schrijver: ...first, let's dive into the VM part a bit. So, could you say that it's a drop-in replacement for any VM where I'm running my current Java code on?
Alina Yurenko: Absolutely. So, migration there is very easy. You just replace your JDK with GraalVM, you point your JAVA_HOME to GraalVM distribution, and you run applications as-is. So, you have all your libraries, tools, IDEs, etc., available to you. There are some minor limitations. I think most users would not necessarily notice them. But, for example, implementing additional GC on a new compiler is not easy, because there is this connection between the compiler and the GC. So, maybe if you want to use some custom GC, that would be not trivial. But other than that, I would say 99.9% of users can easily migrate in a matter of minutes to GraalVM.
Bert Jan Schrijver: And you mentioned that, well, you probably notice performance improvements, right? You also mentioned the JIT, the just-in-time compilation. So, are those improvements coming from better JIT and optimization, or why is GraalVM faster than an average JDK?
Alina Yurenko: I like how you said the GraalVM is faster than the average JDK. I mean, I do agree but notice that I did not say that. You said that, so thank you for that.
Bert Jan Schrijver: I'm just making it up for you.
Alina Yurenko: I appreciate it. Yeah. So, those speedups are coming from the compiler itself, indeed, because the only thing we are replacing in HotSpot VM if you're operating in the just-in-time compilation mode, is the compiler. But the compiler is very good. It's brand-new. It has tons of optimizations that are implemented in it from scratch. And because of all those reasons, and because of those optimizations, we see many applications and many workloads running faster on GraalVM, even as JIT. I think one of the latest such stories, at least that I can recall, is from Facebook. And they moved some of, I think it was data-intensive apps to GraalVM, and they saw something like, I think, a 10% speedup just by switching to GraalVM. So, they didn't do native images. They didn't do any of that, just switched to GraalVM as a JDK.
Bert Jan Schrijver: Okay. Interesting. I think you also read or heard somewhere that you can also use GraalVM in an Oracle Database. Am I correct, or did I get fooled somewhere?
Alina Yurenko: No, no, no. That's very true. I like this question because I don't get asked about it a lot. So, as you mentioned, you have a lot of questions about native images, and people usually have a lot of questions about native images. But this use case, in an Oracle Database, is so cool. So, the way it works is that we have kind of an embedding of GraalVM in the Oracle Database. And it can execute other languages. So, the languages that we call GraalVM languages, are the ones implemented on top of GraalVM. And at the moment, I think the only one available is JavaScript. So, you can execute that right in the Database, so you don't need to kind of extract the data, move it somewhere, process it, put it back. And another benefit is that you can leverage the ecosystem of all those, I don't know, millions of packages that are available in the JavaScript ecosystem, and you can execute that right in your database.
For example, maybe you want to validate some, I don't know, email that it's indeed a valid email, and you can use whatever the JavaScript library is being used for that. And the part I like is that it's a kind of project that shows the kind of value of GraalVM as an ecosystem. Because, in this case, for example, it's an implementation of JavaScript. So, the JavaScript component in GraalVM, and then it's built on top of Truffle, which is our language implementation framework. And the way it is embedded in Oracle Database is through native image. So, the way I understand it, the native image was used to build a shared library of this kind of execution engine. Then it was embedded in the Oracle Database as a shared library. But it's kind of cool that GraalVM's native image is being used to embed something like GraalVM in the database. So, I think it's very cool.
Bert Jan Schrijver: Should I compare this with, for example, having a stored procedure, with SQL, in a database, and now being able to run any JavaScript code as a part of a query or something? How would this work?
Alina Yurenko: To be honest, I haven't looked at that in a while. I know that you can indeed execute JavaScript code right in there. But in terms of other limitations and how it compares to running stored procedures, to be honest, I wouldn't know. Maybe we should write a new blog post and give an update on how it works at the moment. Maybe there are some limitations, but last time I checked, I think it kind of just worked.
Bert Jan Schrijver: Well, it's not something I would envision doing, executing JavaScript in Oracle Database, right?
Alina Yurenko: I mean, it sounds a bit crazy, I must say, but also I think it opens a possibility to use all those JavaScript tools and, like, JavaScript itself as a language, in a database. But I think it's nice to just have more options and access to more tools.
Bert Jan Schrijver: Especially if you can execute logic close to the data, right? You don't need to fetch it over a network boundary. So, that's interesting.
Alina Yurenko: Absolutely.
Recommended talk: Generic or Specific? Making Sensible Software Design Decisions • Bert Jan Schrijver • GOTO 2023
Bert Jan Schrijver: Okay. So, well, before we talk about native images, I think I read there's a community edition and a commercial edition of GraalVM. What is the difference of those? Why would somebody be inclined to go for the commercial edition compared to the community edition?
Alina Yurenko: So, there are indeed two editions. One is Community Edition, and it's open source. All our source code is available on GitHub. Anyone can contribute. Anyone is welcome to contribute. A fun fact, I don't know how to validate that, but somebody said to me that GraalVM might be one of the biggest Java open-source projects out there because it's indeed huge as a project. So, there's the compiler, this language implementation framework, and all the language implementations. So, I don't know if that's true or not, but it sounds pretty cool that it might be one of the biggest open-source Java projects out there. So, that is the Community Edition, and we have one more. It used to be called Enterprise Edition, but now, with the latest release of GraalVM, we have a brand-new distribution of GraalVM, called Oracle GraalVM. And I guess you can compare it to a commercial edition. So, it's available under a free license, meaning you can use all the features that are in that edition for development, for production, and basically all kinds of things, for free, under this new license.
The differences between those editions are, well, A, a license, right? So, one is open source and the one is this GFTC license. But also some features are available in Oracle GraalVM that are not available in Community. And the features, I think the most interesting of them, at least, are around performance, and more specifically, performance in native image. So, in the native image, you now get access to profile-guided optimizations. And maybe we can stop on that when we talk about native images in more detail. You get G1 GC in the native image. And, going back to this JDK JIT use case, outside of the native image, it can also be interesting for users, because the compiler itself has more optimization phases in this kind of commercial addition. So, even if you're running on a JIT, JDK, you might see more performance, hopefully, with this edition.
Native Images in GraalVM
Bert Jan Schrijver: Okay. Well, let's talk about native images. The first time I heard about this was, I think, I don't know, about four, five years ago.
Recommended talk: Maximizing Java Application Performance with GraalVM • Oleg Šelajev • GOTO 2020
Alina Yurenko: Quite a while. Was it from Oleg, or Thomas, or
Bert Jan Schrijver: Yes, probably.
Alina Yurenko: Okay.
Bert Jan Schrijver: And then, well, what are they? You can take a piece of Java code, perform some magic compilation on it, to some target platform, and then there's a native binary that runs on this target platform, right? So, what is native image compilation, and why should anyone want to do it?
Alina Yurenko: It's very interesting. To be honest, the first time I read about it, my mind was blown that something like that is even possible, right? You all know that Java is so dynamic, and it's so powerful because it's so dynamic. So, how do you compile something like Java ahead of time? Because it certainly poses certain limitations, because if you're doing things ahead of time, you need to know everything in advance. So, before I go into this idea behind native image, maybe I should explain how it works at all. So, when you run a native image build command, and give it your application, what happens is that native image looks at your application, starting from its main entry point, and it's trying to find all the reachable code. So, all the code will be executed when your application runs. It tries to find all of that code, and that includes your application code, JDK classes, your dependencies, everything. It's looking for all the reachable code so that it can include only that reachable code in the produced executable, and then eliminate everything else. So, only the things that you need at runtime, only the things that are needed for your application to do what it's supposed to do, only those things will be included in this executable.
So, that is one part of the native image story. Another one, as it's doing so, it's also preparing a heap for you. So, you can start with a prepopulated heap and don't spend time working with that heap when your application starts. But, since we're doing all of this ahead of time, it has to happen under closed-world assumptions. So, everything there is to know about your application needs to be known ahead of time, when we are building your application because otherwise, we just cannot perform this ahead-of-time compilation. Because we are compiling things ahead of time, and also we are eliminating all of this code, loading, execution, and profiling infrastructure from your application. So, in the end, it's only machine code and only the things that are needed for your application to run. Plus, tiny, slim VM implementation, but it's not a full-blown code execution infrastructure anymore. That is so that your application is more lightweight, faster to start, scales better, and doesn't use as much memory. So, this closed-world assumption poses certain challenges. But another way to look at it, it's a different design decision, and along with challenges, I think it brings some important benefits. So, all those startup memories, etc., that native image is famous for, but also some interesting security benefits that maybe we can also talk about further
Bert Jan Schrijver: Sure.
Alina Yurenko: So, yeah. Ahead-of-time compilation under closed-world assumption.
Bert Jan Schrijver: So, just to validate that I've understood you correctly, right? So, if I'm running traditional Java code, I'm compiling my Java code to a bytecode, and then I run this bytecode on a virtual machine, and then the just-in-time compilation, translate this bytecode to machine code, runs on my target platform, right? So, if I'm building a native image, I'm still compiling, probably still compiling my Java code to bytecode first, right?
Alina Yurenko: Absolutely. And that's the part I'm always skipping, because, for me, compiler, it's always the optimizing compiler. That's my bias because I work on GraalVM, but indeed, you need to provide your application to native image in the form of bytecode, so you need to use javac to produce that for bytecode, because as input, it takes bytecode.
Bert Jan Schrijver: So, then, the native image compilation process takes the bytecode, and then there's ahead-of-time compilation to create a machine code for a specific target platform...
Alina Yurenko: Right.
Bert Jan Schrijver: ...right? So... Well, I...
Alina Yurenko: But if I can stop there, because you brought an interesting point about how JVM actually executes code, right? So, just to compare how is that different from native image. So, the way JVM executes code is that when you run application, it will need to load all your classes, look at them, start interpreting, start compiling, start collecting profile information. And all of that is very impressive work that it does, to get the application to that peak performance. But it also comes with certain challenges around startup, especially if you have a larger application, right? Because it's a lot of work to be done when a JVM starts, and needs to warm up and compile your code, and understand everything about your application. So, over time, when it warms up, it does come to great peak performance, but there is a bit of this overhead that you're paying in the beginning, when it has to do all this work. And the idea of native image is to move all of that overhead to build time, so that you can build it once, but then start fast as many times as you need. Because most likely, application will be started more often than it's built. So, in my opinion, it kind of makes sense to move all of that to build time, and then just start when you actually need to start.
Recommended talk: Java in the Cloud with GraalVM • Alina Yurenko • GOTO 2023
Overcoming Challenges in Ahead-of-Time Compilation
Bert Jan Schrijver: But it also sounds difficult, right? Because, well, JIT compilation analyzes code as it runs over time, and then tries to optimize this code for how it is run or actually being used. Whereas if you do ahead-of-time compilation, you don't actually know yet what the use case for this code are going to be, right? So, well, how is it even possible, and how can you get the same, well, or even better performance compared to analyzing something that's running and then optimizing for the stuff that's running?
Alina Yurenko: That's an excellent question, and yeah, the reason why JVM is so powerful is this dynamic code execution, right? It looks at the application on the go, and it adapts to what the application is doing and what is happening at runtime. It can adapt on the go. So, it can make very aggressive optimizations about your code. And then if those assumptions that it made about your code are no longer valid, it can deoptimize, go back to interpret it, and if it runs up again, go back to compile. But it has this flexibility to adapt on the go to what your application does, right? And this is really fascinating about JVM, right? So, how it goes from interpreted to compiled, and then how it can go back, it's really fascinating. And, indeed, native image doesn't have that luxury of adapting on the go, or even being aware of what your application does at runtime. But that's by default. So, what is very cool about native image is that you can use profile-guided optimizations, and that is optimization that allows you to build an instrumented binary of your app, then run it, applying relevant workload, so that native image can look at your app, see what it does, collect this profile information, and then when you are building again a native executable of your app, you can use this profile information to kind of get insight into the future, so, into what your app will actually do at runtime, and build an application with those profiles in mind.
Bert Jan Schrijver: Ah. So, you're basically using runtime profiling information...
Alina Yurenko: Absolutely.
Bert Jan Schrijver: ...to feed into your ahead-of-time compilation, to make it smarter and give it more context.
Alina Yurenko: And I think it's pretty cool, because, in a way, you get best of the both worlds. So, you can optimize application ahead of time. You don't need to spend time on that in runtime, but also you get insight and understanding into runtime behavior of your app. So, I think that's pretty cool.
Profile-Guided Optimizations in Native Images
Bert Jan Schrijver: So, with AOT, you're basically moving whatever the JIT is doing on a JVM to compile time, right? So, your compilation will take longer, but in the end, the startup time probably, and maybe even run time, will take shorter. So, what are typical benefits of, why should I want to run my Java app as a native image? Like, resource usage, or performance, or startup time? Why should I want to do it?
Alina Yurenko: The first benefit people usually bring up is startup time because it's indeed much faster on native images. So, it, again, depends a lot on the app you have, but, I don't know, out of the demos that, for example, I'm showing, like, I would say that an average web server application, doesn't matter which framework, I would say starts about maybe 400 milliseconds in my machine, maybe 200 milliseconds. Then, as an native image, it starts in, I don't know, 30, 40 milliseconds. So, it's order of magnitude faster. And it's indeed impressive, because we don't have to do any of those operations anymore at runtime, right? We are just loading that executable, it has all the data, it can go immediately do whatever it is supposed to do. So, that is startup time, and it's indeed really great, especially for, you know, microservices and serverless application, things like that. So, that's one big benefit. I think everyone always brings that one first.
But I would argue startup time is great, but I would maybe care a bit more about resources usage, especially, again, if I deploy into the cloud and I'm paying for all those resources, so, CPU, memory, etc., that I'm using. So, if I can do the same thing, have the app do the same thing, but use less resources, that probably will be preferable, because I would pay less. Maybe I can deploy more apps at the memory usage of my previous application. And that's pretty cool. And I think I recall this demo that Josh Long did, I think it was Devoxx Belgium, where he had a Spring Boot app running on the JVM, and then he compiled it to native, and he showed the memory usage of the process, and it went down to, I think, like, 100 megabytes probably. And he said, "Who in the room here ever deployed a JVM app that used one gig of memory?" You know, many people raised their hands, and he said, "Okay. This shows you that you can deploy 10 such apps for the same memory footprint. How cool is that?" So, I would argue [inaudible 00:19:18] that that is more even more important. So, you can either reduce your resources, clouds, infrastructure usage, or maybe you can deploy more apps at the runtime impact of your previous app.
Bert Jan Schrijver: I guess with, the startup time only matters if you're in a scale-back-to-zero situation, right? Like, serverless or whatever, and when the user needs to wait for the app to start up, obviously, then startup time matters. But for a typical enterprise-y app that runs for weeks or months, then the startup time doesn't really matter, I guess.
Alina Yurenko: Probably not that much. Probably indeed more for microservices and serverless applications.
Bert Jan Schrijver: So, if I have a JVM-based application, then I need to have a, well, a JRE running on my machine. I need to deploy my code there, and then running, and it will start up, start reading my classes, and will start the JIT process. Do I still need a JDK on my target machine if I build a native image, or is it all packaged in? How does this work?
Alina Yurenko: So, you mean if you want to deploy your application as a native image, do you need a JDK again or not?
Bert Jan Schrijver: On the target server I'm deploying to.
Alina Yurenko: No. So, the target server doesn't need to have anything at all. So, if you are... But you need, as you mentioned, you need to build for the target platform and architecture, right? So, if you have such an opportunity, I don't know if you're building on a Linux machine and you're deploying to a Linux machine, that machine that you're deploying to doesn't need to have anything, because it's a native app in the end, right? So, it just runs fully functional, and so on. And then there are ways to build native images in a fully static way, where all the dependencies are included in the static native image.
Bert Jan Schrijver: So, I would still need a JDK for building and compiling it?
Alina Yurenko: But for developing, you probably would need a JDK anyway.
Bert Jan Schrijver: But in the end, since you're going straight to machine code, you can deploy the machine code. Okay. So, probably that would save you on some disk space as well, compared to…
Recommended talk: Building Optimized Java Microservices with Micronaut 4 & GraalVM • Graeme Rocher • GOTO 2023
Alina Yurenko: We talked about startup, we talked about memory, obviously, packaging size is another benefit, right, but saving disk space per se, but also scaling, right? So, if you want to scale your deployments, that maybe smaller images would also matter to you. And we can probably talk about performance, but that will be, I guess, a big topic. So, before we go into that, there's also very interesting security benefits around native image. And I like talking about it because I think people don't talk about it enough, and they are always very surprised when they talk about security in native image. But it's indeed very interesting. So, all those things we talked about, native image and the build process, and how, in a way, it can seem limiting.
I think it shines in a whole different way when we talk about security, because A, native image eliminates all code that you're not using. So, let's say you're pulling in tons of dependencies, and maybe you're not using them that much, or some dependency looks kind of suspicious to you, but you still want to use, like, a fraction of it. So, native image will eliminate everything you're not using. And that's one way how it reduces attack surface. And also, for example, some vector attacks around just-in-time code compilation are not, just, not possible in native image because there is no longer code compilation happening at all. And also, at runtime, you cannot load new classes, you cannot do reflection and serialization unless you specifically enabled it. And it can be seen as a limitation, but also you have a bit more fine-grade control over your app, and what it does, and what is happening in it. Because if you want to do the reflection, you would need to specify it, or the specification needs to be coming from framework library, etc., but there are no kind of sketchy things happening without you being aware of it. So, there are also some interesting benefits around security too.
Bert Jan Schrijver: So, you probably won't have any issues regarding to dynamic class loading, reflection, serialization, because, well, it's just not there, then, right?
Alina Yurenko: Or, it's there, but it has been specifically configured and allowed by you. So, you need to enable those things for them to work. So, yeah, it won't be happening without you being aware.
Does GraalVM support Reflection?
Bert Jan Schrijver: So, how about reflection? Let's say I'm dynamically loading some classes in my Java code. There's probably no dynamic class loader in the native image, right? So, how do you do this?
Alina Yurenko: So, reflection works in a way that...I mean, there was this huge misconception that GraalVM doesn't support reflection. So, hopefully, we have passed that, and anyone knows that it supports reflection, but there are things to be aware of. So, there are multiple ways how reflection can happen in native image. A, if your framework library, etc., are doing something that has to do with reflection, they would need to provide configuration for native image, to tell native image that, "Hey, we want to use reflection in this and that class." Maybe we want to access, for example, this field, so that has to be specified in a config file that is being fed into native image. And then it can build an app that is aware of that reflection usage, and can work with that reflection usage. So, that is one part of how reflection works in native image.
Now, some of, kind of, more predictable reflection API calls, native image can figure out on its own. So, as it is building application, it...calls that are a bit more trivial and predictable and make sense, native image can figure out on its own, so maybe there would be no more configuration happening from you at all. It can just make it work. And then the last way how this can work is that we have this tracing agent in native image. And you can run your application on the JVM, and it will do what it is supposed to do, and this tracing agent will look at that, and it will produce this config for you, so you don't need to produce it manually. But as a last resort, if you had to produce it manually, maybe you have [inaudible 00:24:56] a smaller app or something, the reflection config is basically a JSON file where you specify, in the preselect format, what and how you want to use reflectively, and native image can build an app that is aware of that.
Bert Jan Schrijver: So, basically you need to pre-specify whatever your code does reflectively.
Alina Yurenko: Yes. Because, again, closed-world assumption, and it gives you all those benefits, but you need to, like, for all those dynamic Java features, you need to tell native image how you are planning to use them, because otherwise, it most likely cannot figure it out automatically under closed-world assumption, because runtime hasn't happened yet, basically.
From JVM to Native Imaging
Bert Jan Schrijver: Let's say that I'm now building apps that run on the JVM, and I want to go into native images. Can I take any random Java application and boom, create a native image of it and get all those advantages right away?
Alina Yurenko: It depends. It depends on what your app does, which dependences it's using, and, again, on your usage of those things like reflection, serialization, resources, etc. My recommendation would be, is that most likely, you're using some kind of framework, and there are many and many frameworks in the Java ecosystem that are likely supporting native image out of the box. So, if you're using something like Spring Boot, Micronaut, Quarkus, and that's, I would say, a majority of the apps probably, have support for native image. So, you would just need to check if you are using the version of the framework, for example, that already introduced support for native image, and then things will be significantly easier for you.
That is one part of how you can make it happen. Another part, if you are not using those frameworks, there is also a way to approach using dependencies. That is if you want to use some library, and let's say that library is using reflection, then it's tricky for native image, as we established. So, you can either provide configuration for reflection that library yourself, but most likely it's challenging because you're not the maintainer of the library, so maybe you don't know it that well. In that case, it's better if the library is providing configuration for native image within the library itself, kind of embedded. Luckily, we see a lot of that happening right now. So, if you go and check many of libraries, their source code, they already provide configuration for native image for their users, which is very nice.
But also we understand that for some libraries, it's maybe a bit more challenging to adopt native image, and they haven't done it yet. So, for that, we created this centralized repo on GitHub, where library and framework authors, but also just normal native image users, can contribute, share, and then reuse all this configuration for native image. And I think it's very cool because it's indeed maybe you're trying to solve reflection for library X, but somebody else already had the challenge, and they had it solved, so why not share this work in other communities, so we can all benefit from it? So, we have the centralized repo, and it's also integrated with our Maven and Gradle plugins, and many frameworks picked it up as well. So, at the point, it works so well that you can, for example, build a native image app, and if you're using those plugins or if you're using one of those frameworks, that config will be picked up automatically, maybe without you being aware of it, if you're not looking carefully at the, like, native image build command. So, let's say you're using, okay, H2 is not necessary because it provides config, but let's say you're using some library that doesn't provide config, but it is in this repo, so our plugins will pull config from that repo, and will produce, hopefully, a fully functional app. So, that should help.
Bert Jan Schrijver: Sure. Okay. So, would you say it's relatively doable to transform a regular Java app into a native image nowadays?
Alina Yurenko: But again, depends on what is a regular app, right?
Bert Jan Schrijver: Sure. Yeah. I remember looking into this years ago, and it was pretty hard, but I imagine that's...
Alina Yurenko: It got better now. I would not say that, like, every single Java app in the world will compile to native, you know, as you just take it and compile it. So, it might or it might not. It depends. So, I would not promise you that every single Java app in the world would compile to native just like that. But if you are starting a newer app and if you're using one of those frameworks, I think it will be optimistic enough to say that it should just work.
Resources
Bert Jan Schrijver: Okay. Good. So, what if somebody who's watching wants to get started with GraalVM right away? What are good resources for them to get started with?
Alina Yurenko: Yes. We have very nice website, graalvm.org. And there you can find basically all the things you need. So, we have recommendations, we have samples, we have reference manuals for things like native image, etc. So, probably that would be a good place to start. And also we have this GraalVM demos repo on GitHub, where you can just go through our demos and build them and run them, so you don't need to create any of that code yourself. If you just want to give GraalVM a try, but you're not ready yet to compile your own application, you can just get our demos from GitHub and compile them, and see how that works for you.
Bert Jan Schrijver: Okay. Thank you. Well, thanks a lot for your time and your explanations.
Alina Yurenko: Sure.
Bert Jan Schrijver: I have more knowledge now, but also more questions. I think I need to dive in it myself. Well, I hope you learned something in this episode of "GOTO Unscripted." So, thanks for watching, and maybe see you at next edition.
Alina Yurenko: Thank you.