Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enabled building containers and running examples/demos on the cloud (OCI) #99

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Prev Previous commit
Updated README with editing suggestions from PR
  • Loading branch information
krisfoster authored and neomatrix369 committed Jan 18, 2022
commit 17b88f5bcabb06789db9e962528e23285ac41124
44 changes: 24 additions & 20 deletions native-image-workshop/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,31 +10,35 @@
We are going to use a fairly trivial application to walk through using GraalVM Native Image. Along the way we will see:

1. How you can turn a Java app into a native executable
2. How you can build a GraalVM Native IMage that works with the dynamic parts of Jva
2. How you can build a native image that works with the dynamic parts of Java
3. Using the command line tools for generating a native image, as well as using the Maven tooling

So what is going to be our testbed application? We will use a command line Java application that counts the number of files within the current directory and sub directories. As a nice extra it also calculates their total size.

As you work through this workshop you will need to update the code, in the following steps.

This workshop relies on using GraalVM 21.3 or higher, with the GraalVM Native Image package installed. It will work with either Community Edition (CE), or Enterprise Edition (EE). If there is any EE speific code / configuration, this will be clearly marked out.
This workshop relies on using GraalVM 21.3 or higher, with GraalVM Native Image installed. It will work with either Community Edition (CE), or Enterprise Edition (EE). If there is any EE speific code / configuration, this will be clearly marked out.

Let's beign!

## Setup

Install GraalVM. Instructions can be found [here](https://www.graalvm.org/docs/getting-started/.
Install GraalVM. Instructions can be found on the website:

[Linux](https://www.graalvm.org/docs/getting-started/linux/)
[macOS](https://www.graalvm.org/docs/getting-started/macos/)
[Windows](https://www.graalvm.org/docs/getting-started/windows/)

You will need the following installed:

* GraalVM 21.3.0 JDK 11 or JDK17 installed (either EE or CE)
* GraalVM 21.3.0 JDK 11 or JDK17 installed (either Enterprise Edition or Community Edition)
* Native Image plugin that matches your GraalVM installation

## Quick Note on Using Maven Profiles

This workshop will use Maven profiles. Proflies are a great way to have different build configurtions within a single `pom.xml` file. You can find out more about them [here](https://maven.apache.org/guides/introduction/introduction-to-profiles.html).

We will use several profiles throughout the project, each of which will serve a different purpose. We are able to call these profiles by passing a parameter containing the name of the profile to maven. The example below shows how we would call the `JAVA` profile, when building with maven:
We will use several profiles throughout the project, each of which will serve a different purpose. We are able to call these profiles by passing a parameter containing the name of the profile to `mvn`. The example below shows how we would call the `JAVA` profile, when building with maven:

![User Input](./images/userinput.png)
```sh
Expand All @@ -43,17 +47,17 @@ $ mvn clean package -PJAVA

The name of the profile to be called is appended to the `-P` flag. We use these profiles within this workshop (all defined in the `pom.xml` file):

1. `java_agent` : Ths builds the Java application with the tracing agent
2. `native` : This builds the native image
1. `java_agent` : This builds the Java application with the tracing agent. The agent tracks all usages of dynamic features of your application and captures this inforamtion into configuration files
2. `native` : This builds the native executable

## The Java App

The Java application can be found in the `src` directory and it consists of two files.

* `App.java` : A wrapper for the `ListDir` application
* `ListDir.java` : This does all the work, counting the files an summarising the output
* `App.java` : A wrapper for the `ListDir` application
* `ListDir.java` : This does all the work, counting the files and summarising the output

We build our application using a maven, `pom.xml` file. Now we have had a basic understanding of our application, let's build our application and see how it works.
We build our application using a maven, `pom.xml` file. Now we have a basic understanding of our application, let's build our application and see how it works.

## Build the Basic Java App

Expand Down Expand Up @@ -86,9 +90,9 @@ Did it work for you?

## Build a Native Image from the App

Next, you are going to build a native image version of the application. This will start quicker than the Java application.
Next, we are going to build a native image version of the application. This will start quicker than the Java application.

We will do this by hand first, using the `native-image` tool.. To begin, check that you have a compiled uber JAR in your `target` dir:
We will do this by hand first, using the `native-image` tool. To begin, check that you have a compiled uber JAR in your `target` dir:

![User Input](./images/userinput.png)
```sh
Expand All @@ -104,7 +108,7 @@ $ ls ./target

The file you will need is, `graalvmnidemos-1.0-SNAPSHOT-jar-with-dependencies.jar`.

**NOTE** : You will need to have installed the GraalVM Native Image package for GraalVM - see the set up instructions.
**NOTE** : You need to have Native Image plugin installed in GraalVM - see the set up instructions.

Now you can generate a native image as follows, within the root of the project:

Expand Down Expand Up @@ -134,9 +138,9 @@ Compare that to the time running the app with the regular `java` command:
time java -cp ./target/graalvmnidemos-1.0-SNAPSHOT-jar-with-dependencies.jar oracle.App
```

What do the various parameters we passed to the `native-image` command do? Full documentation on these can be found [here](https://www.graalvm.org/reference-manual/native-image/BuildConfiguration/):
What do the various parameters we passed to the `native-image` command do? The full documentation on these can be found [here](https://www.graalvm.org/reference-manual/native-image/BuildConfiguration/):

* `--no-fallback`: Do not generate a fallback image. A fallback image requires the JVM to run, and we do not want this.We just want it to be a native image.
* `--no-fallback`: Do not generate a fallback image. A fallback image requires the JVM to run, and we do not want this. We just want it to be a native image.
* `-H:Class`: Tell the `native-image` builder which class is the entry point method (the `main` method).
* `-H:Name`: Specify what the output executable file should be called.

Expand Down Expand Up @@ -165,9 +169,9 @@ We can also run the `native-image` tool using Maven. If you look at the `pom.xml
<imageName>${exe.file.name}</imageName>
<mainClass>${app.main.class}</mainClass>
<buildArgs>
<!-- Don't create a antive exe that falls back to starting a JVM if the image won't build -->
<!-- Don't create a native executable that falls back to starting a JVM if the image won't build -->
<buildArg>--no-fallback</buildArg>
<!-- Warn about features that arent supported by native image at the runtime of the image.
<!-- Warn about features that arent supported by native image at run time.
If there is any reflection, for example, this will generate an error at the runtime of
native image.
-->
Expand Down Expand Up @@ -203,7 +207,7 @@ We've already added it as a dependency in the `pom.xml` file, and it can be seen
</dependency>
```

To add `log4j` all we need to do is to open up the `ListDir.java` file and uncomment some things in order to start using it. Go through and uncomment the various lines that add the imports and the logging code. These are the following lines that need uncommenting:
To add `log4j` all we need to do is to open up the `ListDir.java` file and uncomment some things in order to start using it. Go through and uncomment the various lines that add the imports and the logging code. Uncomment the following lines:

```java
//import org.apache.log4j.Logger;
Expand Down Expand Up @@ -234,14 +238,14 @@ OK, so now we have added logging, let's see if it works by rebuilding and runnin
$ mvn clean package exec:exec
```

Great, that works. Now, let's build a native image using the maven profile:
Great, that works. Now, let's build a native image using the Maven profile:

![User Input](./images/userinput.png)
```sh
$ mvn clean package -Pnative
```

The run the built image:
Then run the executable:

![User Input](./images/userinput.png)
```sh
Expand Down