添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

A native-image is a optimized translation of a java application to OS/CPU specific native code. This new application will have different characteristics from a traditional JVM application, the most notable ones are:

Native images are therefore very well suited for CLI or Serverless but nothing forbids its use also for server applications.

Native image compilation has several restrictions (by design) of which most do not apply to Vert.x core code. This makes vert.x a very good candidate to write native images. There are however, a couple of known limitations that can be easily worked around to build a native image.

This howto will cover these limitations and explain how to adapt a simple vert.x application to become native.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.example</groupId>
  <artifactId>myapp</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <name>hello_native</name>
  <properties>
    <vertx.verticle>vertx.HTTPVerticle</vertx.verticle>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.target>1.8</maven.compiler.target>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.testSource>1.8</maven.compiler.testSource>
    <maven.compiler.testTarget>1.8</maven.compiler.testTarget>
  </properties>
  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>io.vertx</groupId>
        <artifactId>vertx-stack-depchain</artifactId>
        <version>4.0.0.CR2</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
    </dependencies>
  </dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>io.vertx</groupId>
      <artifactId>vertx-core</artifactId>
    </dependency>
    <dependency>
      <groupId>io.vertx</groupId>
      <artifactId>vertx-web-client</artifactId>
    </dependency>
  </dependencies>
  <build>
    <plugins>
      <plugin>
        <groupId>io.reactiverse</groupId>
        <artifactId>vertx-maven-plugin</artifactId>
        <version>1.0.18</version>
        <executions>
          <execution>
            <id>vmp</id>
            <goals>
              <goal>initialize</goal>
              <goal>package</goal>
            </goals>
          </execution>
        </executions>
        <configuration>
          <redeploy>true</redeploy>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

This is a minimal Hello World project. which you can confirm by reading what the code does:

package vertx;
import io.vertx.core.AbstractVerticle;
public class HTTPVerticle extends AbstractVerticle {
  @Override
  public void start() {
    vertx.createHttpServer().requestHandler(req -> {
      req.response()
        .putHeader("content-type", "text/plain")
        .end("Hello from Vert.x!");
    }).listen(8080, listen -> {
      if (listen.succeeded()) {
        System.out.println("Server listening on http://localhost:8080/");
      } else {
        listen.cause().printStackTrace();
        System.exit(1);

Until this moment there is nothing new. It is a plain vert.x java project.

The same applies for the remaining sources (which will be covered later).

<plugin>
  <groupId>org.graalvm.nativeimage</groupId>
  <artifactId>native-image-maven-plugin</artifactId>
  <version>${graal.version}</version>   <!--(1)-->
  <executions>
    <execution>
      <goals>
        <goal>native-image</goal>
      </goals>
      <phase>package</phase>
    </execution>
  </executions>
  <configuration>
    <imageName>${project.name}</imageName>    <!--(2)-->
    <mainClass>${vertx.verticle}</mainClass>  <!--(3)-->
    <buildArgs>-H:+PrintClassInitialization -H:+ReportExceptionStackTraces</buildArgs> <!--(4)-->
  </configuration>
</plugin>
  public static void main(String[] args) {
    Vertx.vertx().deployVerticle(new HTTPVerticle());

Or configure the reflection config of graalvm to not exclude our verticles:

"name": "io.vertx.core.impl.launcher.commands.RunCommand", "allDeclaredConstructors": true, "allDeclaredMethods": true "name": "io.vertx.core.impl.launcher.commands.VertxIsolatedDeployer", "allDeclaredConstructors": true, "allDeclaredMethods": true "name": "java.lang.Long", "allDeclaredConstructors": true "name": "java.lang.Integer", "allDeclaredConstructors": true "name": "vertx.HTTPVerticle", "allDeclaredConstructors": true, "allDeclaredMethods": true "name": "vertx.HTTPSVerticle", "allDeclaredConstructors": true, "allDeclaredMethods": true "name": "vertx.APIClientVerticle", "allDeclaredConstructors": true, "allDeclaredMethods": true

Adding support to SSL is not difficult but requires some updates. The reason is that security libraries will increase your final binary size considerably so all security features are disabled behind flags. There are also other caveats such as java keystores are allowed BUT must be in PKCS12 which is the new default format since Java9 but not on Java8 (which graalvm is based on).

You will now add an HTTPS vertcle server to your project, create the class HTTPSVerticle in the vertx package next to the existing one:

package vertx;
import io.vertx.core.AbstractVerticle;
import io.vertx.core.http.HttpServerOptions;
import io.vertx.core.net.JksOptions;
public class HTTPSVerticle extends AbstractVerticle {
  @Override
  public void start() {
    vertx.createHttpServer(
      new HttpServerOptions()
        .setSsl(true)             // (1)
        .setKeyStoreOptions(
          new JksOptions()
            .setPath("certificates.keystore")   // (2)
            .setPassword("localhost")           // (3)
    ).requestHandler(req -> {
      req.response()
        .putHeader("content-type", "text/plain")
        .end("Hello from Vert.x!");
    }).listen(8443, listen -> {
      if (listen.succeeded()) {
        System.out.println("Server listening on https://localhost:8443/");
      } else {
        listen.cause().printStackTrace();
        System.exit(1);
  -importkeystore \
  -srckeystore certificates.keystore \
  -destkeystore certificates.keystore \
  -deststoretype pkcs12

If you build the image this will compile, but won’t work at runtime. One thing is needed:

<imageName>${project.name}</imageName> <mainClass>${vertx.verticle}</mainClass> <buildArgs>--enable-all-security-services</buildArgs> </configuration>
import io.vertx.core.AbstractVerticle; import io.vertx.core.buffer.Buffer; import io.vertx.ext.web.client.HttpResponse; import io.vertx.ext.web.client.WebClient; import io.vertx.ext.web.client.WebClientOptions; public class APIClientVerticle extends AbstractVerticle { @Override public void start() { WebClient client = WebClient.create(vertx, new WebClientOptions().setSsl(true).setTrustAll(true)); client .get(443, "icanhazdadjoke.com", "/") .putHeader("Accept", "text/plain") .send(ar -> { if (ar.succeeded()) { HttpResponse<Buffer> response = ar.result(); System.out.println("Got HTTP response with status " + response.statusCode() + " with data " + response.body().toString("ISO-8859-1")); } else { ar.cause().printStackTrace(); // Submit our API request and then exit (to make testing easier) getVertx().close();

This client will make a HTTPS request and print the output on the console.

<?xml version="1.0" encoding="UTF-8" ?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.example</groupId>
  <artifactId>myapp</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <name>hello_native</name>
  <properties>
    <vertx.version>4.3.5</vertx.version>
    <graal.plugin.version>0.9.8</graal.plugin.version>
    <vertx.plugin.version>1.0.22</vertx.plugin.version>
    <failsafe.plugin.version>2.22.2</failsafe.plugin.version>
    <junit5.webclient.version>0.3.0</junit5.webclient.version>
    <vertx.verticle>vertx.APIClientVerticle</vertx.verticle>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.target>1.8</maven.compiler.target>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.testSource>1.8</maven.compiler.testSource>
    <maven.compiler.testTarget>1.8</maven.compiler.testTarget>
  </properties>
  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>io.vertx</groupId>
        <artifactId>vertx-stack-depchain</artifactId>
        <version>${vertx.version}</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
    </dependencies>
  </dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>io.vertx</groupId>
      <artifactId>vertx-core</artifactId>
    </dependency>
    <dependency>
      <groupId>io.vertx</groupId>
      <artifactId>vertx-web-client</artifactId>
    </dependency>
    <dependency>
      <groupId>io.vertx</groupId>
      <artifactId>vertx-junit5</artifactId>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>io.reactiverse</groupId>
      <artifactId>reactiverse-junit5-web-client</artifactId>
      <version>${junit5.webclient.version}</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
  <build>
    <plugins>
      <plugin>
        <groupId>io.reactiverse</groupId>
        <artifactId>vertx-maven-plugin</artifactId>
        <version>${vertx.plugin.version}</version>
        <executions>
          <execution>
            <id>vmp</id>
            <goals>
              <goal>initialize</goal>
            </goals>
          </execution>
        </executions>
        <configuration>
          <redeploy>true</redeploy>
        </configuration>
      </plugin>
      <plugin>
        <groupId>org.graalvm.buildtools</groupId>
        <artifactId>native-maven-plugin</artifactId>
        <version>${graal.plugin.version}</version>
        <executions>
          <execution>
            <goals>
              <goal>build</goal>
            </goals>
            <phase>package</phase>
          </execution>
        </executions>
        <configuration>
          <imageName>${project.name}</imageName>
          <mainClass>io.vertx.core.Launcher</mainClass>
          <buildArgs>-H:+PrintClassInitialization -H:+ReportExceptionStackTraces</buildArgs>
        </configuration>
      </plugin>
      <plugin>
        <artifactId>maven-failsafe-plugin</artifactId>
        <version>${failsafe.plugin.version}</version>
        <executions>
          <execution>
            <goals>
              <goal>integration-test</goal>
              <goal>verify</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
</project>

Running mvn clean package will render a build failure. Currently and because vertx-core still depends on a netty release older than 4.1.53, we need to import the configuration added upstream manually. Which means we need to add a new file:

├── pom.xml
└── src
    └── main
        └── resources
            └── META-INF/native-image/com.example/myapp
                └── native-image.properties

This file are the configuration needed to be passed to the compiler. Currently the file is quite big but again once vertx core uses the latest netty many of these entries can be removed and only list the vert.x specific ones:

Args =\
--enable-http \
--enable-https \
--allow-incomplete-classpath \
-H:EnableURLProtocols=http,https \
--report-unsupported-elements-at-runtime \
-H:ReflectionConfigurationResources=${.}/reflect-config.json \
-H:JNIConfigurationResources=${.}/jni-config.json \
-H:ResourceConfigurationResources=${.}/resource-config.json \
--initialize-at-run-time=\
io.netty.handler.codec.compression.ZstdOptions

Running a compilation will be:

$ mvn package
[INFO] Scanning for projects...
[INFO]
[INFO] -------------------------< com.example:myapp >--------------------------
[INFO] Building hello_native 0.0.1-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ myapp ---
[INFO] Deleting /home/paulo/Projects/vertx-howtos/graal-native-image-howto/steps/step-2/target
[INFO]
[INFO] --- vertx-maven-plugin:1.0.22:initialize (vmp) @ myapp ---
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ myapp ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 4 resources
[INFO]
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ myapp ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 3 source files to /home/paulo/Projects/vertx-howtos/graal-native-image-howto/steps/step-2/target/classes
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ myapp ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory /home/paulo/Projects/vertx-howtos/graal-native-image-howto/steps/step-2/src/test/resources
[INFO]
[INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ myapp ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to /home/paulo/Projects/vertx-howtos/graal-native-image-howto/steps/step-2/target/test-classes
[INFO]
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ myapp ---
[INFO]
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ myapp ---
[INFO] Building jar: /home/paulo/Projects/vertx-howtos/graal-native-image-howto/steps/step-2/target/myapp-0.0.1-SNAPSHOT.jar
[INFO]
[INFO] --- native-maven-plugin:0.9.8:build (default) @ myapp ---
[INFO] ImageClasspath Entry: io.vertx:vertx-core:jar:4.3.5:compile (file:///home/paulo/.m2/repository/io/vertx/vertx-core/4.3.5/vertx-core-4.3.5.jar)
[INFO] ImageClasspath Entry: io.netty:netty-common:jar:4.1.85.Final:compile (file:///home/paulo/.m2/repository/io/netty/netty-common/4.1.85.Final/netty-common-4.1.85.Final.jar)
[INFO] ImageClasspath Entry: io.netty:netty-buffer:jar:4.1.85.Final:compile (file:///home/paulo/.m2/repository/io/netty/netty-buffer/4.1.85.Final/netty-buffer-4.1.85.Final.jar)
[INFO] ImageClasspath Entry: io.netty:netty-transport:jar:4.1.85.Final:compile (file:///home/paulo/.m2/repository/io/netty/netty-transport/4.1.85.Final/netty-transport-4.1.85.Final.jar)
[INFO] ImageClasspath Entry: io.netty:netty-handler:jar:4.1.85.Final:compile (file:///home/paulo/.m2/repository/io/netty/netty-handler/4.1.85.Final/netty-handler-4.1.85.Final.jar)
[INFO] ImageClasspath Entry: io.netty:netty-transport-native-unix-common:jar:4.1.85.Final:compile (file:///home/paulo/.m2/repository/io/netty/netty-transport-native-unix-common/4.1.85.Final/netty-transport-native-unix-common-4.1.85.Final.jar)
[INFO] ImageClasspath Entry: io.netty:netty-codec:jar:4.1.85.Final:compile (file:///home/paulo/.m2/repository/io/netty/netty-codec/4.1.85.Final/netty-codec-4.1.85.Final.jar)
[INFO] ImageClasspath Entry: io.netty:netty-handler-proxy:jar:4.1.85.Final:compile (file:///home/paulo/.m2/repository/io/netty/netty-handler-proxy/4.1.85.Final/netty-handler-proxy-4.1.85.Final.jar)
[INFO] ImageClasspath Entry: io.netty:netty-codec-socks:jar:4.1.85.Final:compile (file:///home/paulo/.m2/repository/io/netty/netty-codec-socks/4.1.85.Final/netty-codec-socks-4.1.85.Final.jar)
[INFO] ImageClasspath Entry: io.netty:netty-codec-http:jar:4.1.85.Final:compile (file:///home/paulo/.m2/repository/io/netty/netty-codec-http/4.1.85.Final/netty-codec-http-4.1.85.Final.jar)
[INFO] ImageClasspath Entry: io.netty:netty-codec-http2:jar:4.1.85.Final:compile (file:///home/paulo/.m2/repository/io/netty/netty-codec-http2/4.1.85.Final/netty-codec-http2-4.1.85.Final.jar)
[INFO] ImageClasspath Entry: io.netty:netty-resolver:jar:4.1.85.Final:compile (file:///home/paulo/.m2/repository/io/netty/netty-resolver/4.1.85.Final/netty-resolver-4.1.85.Final.jar)
[INFO] ImageClasspath Entry: io.netty:netty-resolver-dns:jar:4.1.85.Final:compile (file:///home/paulo/.m2/repository/io/netty/netty-resolver-dns/4.1.85.Final/netty-resolver-dns-4.1.85.Final.jar)
[INFO] ImageClasspath Entry: io.netty:netty-codec-dns:jar:4.1.85.Final:compile (file:///home/paulo/.m2/repository/io/netty/netty-codec-dns/4.1.85.Final/netty-codec-dns-4.1.85.Final.jar)
[INFO] ImageClasspath Entry: com.fasterxml.jackson.core:jackson-core:jar:2.14.0:compile (file:///home/paulo/.m2/repository/com/fasterxml/jackson/core/jackson-core/2.14.0/jackson-core-2.14.0.jar)
[INFO] ImageClasspath Entry: io.vertx:vertx-web-client:jar:4.3.5:compile (file:///home/paulo/.m2/repository/io/vertx/vertx-web-client/4.3.5/vertx-web-client-4.3.5.jar)
[INFO] ImageClasspath Entry: io.vertx:vertx-uri-template:jar:4.3.5:compile (file:///home/paulo/.m2/repository/io/vertx/vertx-uri-template/4.3.5/vertx-uri-template-4.3.5.jar)
[INFO] ImageClasspath Entry: io.vertx:vertx-web-common:jar:4.3.5:compile (file:///home/paulo/.m2/repository/io/vertx/vertx-web-common/4.3.5/vertx-web-common-4.3.5.jar)
[INFO] ImageClasspath Entry: io.vertx:vertx-auth-common:jar:4.3.5:compile (file:///home/paulo/.m2/repository/io/vertx/vertx-auth-common/4.3.5/vertx-auth-common-4.3.5.jar)
[INFO] ImageClasspath Entry: com.example:myapp:jar:0.0.1-SNAPSHOT (file:///home/paulo/Projects/vertx-howtos/graal-native-image-howto/steps/step-2/target/myapp-0.0.1-SNAPSHOT.jar)
[INFO] Executing: /home/paulo/.jdks/graalvm-ce-java11-22.3.0/bin/native-image -cp /home/paulo/.m2/repository/io/vertx/vertx-core/4.3.5/vertx-core-4.3.5.jar:/home/paulo/.m2/repository/io/netty/netty-common/4.1.85.Final/netty-common-4.1.85.Final.jar:/home/paulo/.m2/repository/io/netty/netty-buffer/4.1.85.Final/netty-buffer-4.1.85.Final.jar:/home/paulo/.m2/repository/io/netty/netty-transport/4.1.85.Final/netty-transport-4.1.85.Final.jar:/home/paulo/.m2/repository/io/netty/netty-handler/4.1.85.Final/netty-handler-4.1.85.Final.jar:/home/paulo/.m2/repository/io/netty/netty-transport-native-unix-common/4.1.85.Final/netty-transport-native-unix-common-4.1.85.Final.jar:/home/paulo/.m2/repository/io/netty/netty-codec/4.1.85.Final/netty-codec-4.1.85.Final.jar:/home/paulo/.m2/repository/io/netty/netty-handler-proxy/4.1.85.Final/netty-handler-proxy-4.1.85.Final.jar:/home/paulo/.m2/repository/io/netty/netty-codec-socks/4.1.85.Final/netty-codec-socks-4.1.85.Final.jar:/home/paulo/.m2/repository/io/netty/netty-codec-http/4.1.85.Final/netty-codec-http-4.1.85.Final.jar:/home/paulo/.m2/repository/io/netty/netty-codec-http2/4.1.85.Final/netty-codec-http2-4.1.85.Final.jar:/home/paulo/.m2/repository/io/netty/netty-resolver/4.1.85.Final/netty-resolver-4.1.85.Final.jar:/home/paulo/.m2/repository/io/netty/netty-resolver-dns/4.1.85.Final/netty-resolver-dns-4.1.85.Final.jar:/home/paulo/.m2/repository/io/netty/netty-codec-dns/4.1.85.Final/netty-codec-dns-4.1.85.Final.jar:/home/paulo/.m2/repository/com/fasterxml/jackson/core/jackson-core/2.14.0/jackson-core-2.14.0.jar:/home/paulo/.m2/repository/io/vertx/vertx-web-client/4.3.5/vertx-web-client-4.3.5.jar:/home/paulo/.m2/repository/io/vertx/vertx-uri-template/4.3.5/vertx-uri-template-4.3.5.jar:/home/paulo/.m2/repository/io/vertx/vertx-web-common/4.3.5/vertx-web-common-4.3.5.jar:/home/paulo/.m2/repository/io/vertx/vertx-auth-common/4.3.5/vertx-auth-common-4.3.5.jar:/home/paulo/Projects/vertx-howtos/graal-native-image-howto/steps/step-2/target/myapp-0.0.1-SNAPSHOT.jar -H:+PrintClassInitialization -H:+ReportExceptionStackTraces -H:Class=io.vertx.core.Launcher -H:Name=hello_native
Warning: Using a deprecated option --allow-incomplete-classpath from 'META-INF/native-image/com.example/myapp/native-image.properties' in 'file:///home/paulo/Projects/vertx-howtos/graal-native-image-howto/steps/step-2/target/myapp-0.0.1-SNAPSHOT.jar'. Allowing an incomplete classpath is now the default. Use --link-at-build-time to report linking errors at image build time for a class or package.
========================================================================================================================
GraalVM Native Image: Generating 'hello_native' (executable)...
========================================================================================================================
Warning: Could not register io.netty.handler.codec.compression.Lz4FrameDecoder: queryAllPublicMethods for reflection. Reason: java.lang.NoClassDefFoundError: net/jpountz/lz4/LZ4Exception.
Warning: Could not register io.netty.handler.codec.compression.Lz4FrameEncoder: queryAllPublicMethods for reflection. Reason: java.lang.NoClassDefFoundError: net/jpountz/lz4/LZ4Exception.
Warning: Could not register io.netty.handler.codec.marshalling.CompatibleMarshallingDecoder: queryAllPublicMethods for reflection. Reason: java.lang.NoClassDefFoundError: org/jboss/marshalling/ByteInput.
Warning: Could not register io.netty.handler.codec.marshalling.CompatibleMarshallingEncoder: queryAllPublicMethods for reflection. Reason: java.lang.NoClassDefFoundError: org/jboss/marshalling/ByteOutput.
Warning: Could not register io.netty.handler.codec.marshalling.MarshallingDecoder: queryAllPublicMethods for reflection. Reason: java.lang.NoClassDefFoundError: org/jboss/marshalling/ByteInput.
Warning: Could not register io.netty.handler.codec.marshalling.MarshallingEncoder: queryAllPublicMethods for reflection. Reason: java.lang.NoClassDefFoundError: org/jboss/marshalling/ByteOutput.
Warning: Could not register io.netty.handler.codec.protobuf.ProtobufDecoder: queryAllPublicMethods for reflection. Reason: java.lang.NoClassDefFoundError: com/google/protobuf/ExtensionRegistryLite.
Warning: Could not register io.netty.handler.codec.compression.Lz4FrameDecoder: queryAllPublicMethods for reflection. Reason: java.lang.NoClassDefFoundError: net/jpountz/lz4/LZ4Exception.
Warning: Could not register io.netty.handler.codec.compression.Lz4FrameEncoder: queryAllPublicMethods for reflection. Reason: java.lang.NoClassDefFoundError: net/jpountz/lz4/LZ4Exception.
Warning: Could not register io.netty.handler.codec.marshalling.CompatibleMarshallingDecoder: queryAllPublicMethods for reflection. Reason: java.lang.NoClassDefFoundError: org/jboss/marshalling/ByteInput.
Warning: Could not register io.netty.handler.codec.marshalling.CompatibleMarshallingEncoder: queryAllPublicMethods for reflection. Reason: java.lang.NoClassDefFoundError: org/jboss/marshalling/ByteOutput.
Warning: Could not register io.netty.handler.codec.marshalling.MarshallingDecoder: queryAllPublicMethods for reflection. Reason: java.lang.NoClassDefFoundError: org/jboss/marshalling/ByteInput.
Warning: Could not register io.netty.handler.codec.marshalling.MarshallingEncoder: queryAllPublicMethods for reflection. Reason: java.lang.NoClassDefFoundError: org/jboss/marshalling/ByteOutput.
Warning: Could not register io.netty.handler.codec.protobuf.ProtobufDecoder: queryAllPublicMethods for reflection. Reason: java.lang.NoClassDefFoundError: com/google/protobuf/ExtensionRegistryLite.
[1/7] Initializing...                                                                                    (2.9s @ 0.24GB)
 Version info: 'GraalVM 22.3.0 Java 11 CE'
 Java version info: '11.0.17+8-jvmci-22.3-b08'
 C compiler: gcc (linux, x86_64, 12.2.0)
 Garbage collector: Serial GC
# Printing class initialization configuration to: /home/paulo/Projects/vertx-howtos/graal-native-image-howto/steps/step-2/target/reports/class_initialization_configuration_20221129_125610.csv
[2/7] Performing analysis...  [*WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by io.netty.util.internal.ReflectionUtil (file:/home/paulo/.m2/repository/io/netty/netty-common/4.1.85.Final/netty-common-4.1.85.Final.jar) to constructor java.nio.DirectByteBuffer(long,int)
WARNING: Please consider reporting this to the maintainers of io.netty.util.internal.ReflectionUtil
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
Nov 29, 2022 12:56:21 PM io.netty.handler.ssl.BouncyCastleAlpnSslUtils <clinit>
SEVERE: Unable to initialize BouncyCastleAlpnSslUtils.
java.lang.ClassNotFoundException: org.bouncycastle.jsse.BCSSLEngine
	at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:476)
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:589)
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
	at java.base/java.lang.Class.forName0(Native Method)
	at java.base/java.lang.Class.forName(Class.java:315)
	at io.netty.handler.ssl.BouncyCastleAlpnSslUtils.<clinit>(BouncyCastleAlpnSslUtils.java:63)
	at java.base/jdk.internal.misc.Unsafe.ensureClassInitialized0(Native Method)
	at java.base/jdk.internal.misc.Unsafe.ensureClassInitialized(Unsafe.java:1042)
	at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.classinitialization.ClassInitializationSupport.ensureClassInitialized(ClassInitializationSupport.java:172)
	at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.classinitialization.ProvenSafeClassInitializationSupport.computeInitKindAndMaybeInitializeClass(ProvenSafeClassInitializationSupport.java:344)
	at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.classinitialization.ProvenSafeClassInitializationSupport.computeInitKindAndMaybeInitializeClass(ProvenSafeClassInitializationSupport.java:75)
	at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.classinitialization.ClassInitializationSupport.shouldInitializeAtRuntime(ClassInitializationSupport.java:148)
	at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.SVMHost.isInitialized(SVMHost.java:297)
	at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.meta.AnalysisType.isInitialized(AnalysisType.java:882)
	at jdk.internal.vm.compiler/org.graalvm.compiler.java.BytecodeParser.maybeEagerlyInitialize(BytecodeParser.java:4304)
	at jdk.internal.vm.compiler/org.graalvm.compiler.java.BytecodeParser.genInvokeStatic(BytecodeParser.java:1658)
	at jdk.internal.vm.compiler/org.graalvm.compiler.java.BytecodeParser.genInvokeStatic(BytecodeParser.java:1651)
	at jdk.internal.vm.compiler/org.graalvm.compiler.java.BytecodeParser.processBytecode(BytecodeParser.java:5288)
	at jdk.internal.vm.compiler/org.graalvm.compiler.java.BytecodeParser.iterateBytecodesForBlock(BytecodeParser.java:3385)
	at jdk.internal.vm.compiler/org.graalvm.compiler.java.BytecodeParser.handleBytecodeBlock(BytecodeParser.java:3345)
	at jdk.internal.vm.compiler/org.graalvm.compiler.java.BytecodeParser.processBlock(BytecodeParser.java:3190)
	at jdk.internal.vm.compiler/org.graalvm.compiler.java.BytecodeParser.build(BytecodeParser.java:1138)
	at jdk.internal.vm.compiler/org.graalvm.compiler.java.BytecodeParser.buildRootMethod(BytecodeParser.java:1030)
	at jdk.internal.vm.compiler/org.graalvm.compiler.java.GraphBuilderPhase$Instance.run(GraphBuilderPhase.java:97)
	at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.phases.SharedGraphBuilderPhase.run(SharedGraphBuilderPhase.java:84)
	at jdk.internal.vm.compiler/org.graalvm.compiler.phases.Phase.run(Phase.java:49)
	at jdk.internal.vm.compiler/org.graalvm.compiler.phases.BasePhase.apply(BasePhase.java:446)
	at jdk.internal.vm.compiler/org.graalvm.compiler.phases.Phase.apply(Phase.java:42)
	at jdk.internal.vm.compiler/org.graalvm.compiler.phases.Phase.apply(Phase.java:38)
	at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.flow.AnalysisParsedGraph.parseBytecode(AnalysisParsedGraph.java:135)
	at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.meta.AnalysisMethod.ensureGraphParsed(AnalysisMethod.java:685)
	at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.flow.MethodTypeFlowBuilder.parse(MethodTypeFlowBuilder.java:171)
	at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.flow.MethodTypeFlowBuilder.apply(MethodTypeFlowBuilder.java:349)
	at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.flow.MethodTypeFlow.createFlowsGraph(MethodTypeFlow.java:93)
	at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.flow.MethodTypeFlow.ensureFlowsGraphCreated(MethodTypeFlow.java:83)
	at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.flow.MethodTypeFlow.getOrCreateMethodFlowsGraph(MethodTypeFlow.java:65)
	at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.typestate.DefaultVirtualInvokeTypeFlow.onObservedUpdate(DefaultVirtualInvokeTypeFlow.java:109)
	at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.flow.TypeFlow.lambda$addObserver$0(TypeFlow.java:455)
	at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.util.CompletionExecutor.executeCommand(CompletionExecutor.java:193)
	at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.util.CompletionExecutor.lambda$executeService$0(CompletionExecutor.java:177)
	at java.base/java.util.concurrent.ForkJoinTask$RunnableExecuteAction.exec(ForkJoinTask.java:1426)
	at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:290)
	at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1020)
	at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1656)
	at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1594)
	at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:183)
# Printing class initialization dependencies to: /home/paulo/Projects/vertx-howtos/graal-native-image-howto/steps/step-2/target/reports/class_initialization_dependencies_20221129_125640.dot
# Printing class initialization report to: /home/paulo/Projects/vertx-howtos/graal-native-image-howto/steps/step-2/target/reports/class_initialization_report_20221129_125640.csv
[2/7] Performing analysis...  [**********]                                                              (30.0s @ 4.34GB)
  10,678 (89.69%) of 11,905 classes reachable
  18,919 (64.59%) of 29,293 fields reachable
  55,090 (60.41%) of 91,201 methods reachable
     428 classes,     6 fields, and 1,602 methods registered for reflection
      69 classes,    88 fields, and    56 methods registered for JNI access
       5 native libraries: dl, pthread, rt, stdc++, z
[3/7] Building universe...                                                                               (7.1s @ 2.74GB)
[4/7] Parsing methods...      [**]                                                                       (4.1s @ 2.03GB)
[5/7] Inlining methods...     [***]                                                                      (2.0s @ 3.71GB)
[6/7] Compiling methods...    [*****]                                                                   (27.2s @ 3.15GB)
[7/7] Creating image...                                                                                  (3.0s @ 4.61GB)
  22.78MB (49.38%) for code area:    34,998 compilation units
  21.08MB (45.71%) for image heap:  260,328 objects and 14 resources
   2.26MB ( 4.91%) for other data
  46.12MB in total
------------------------------------------------------------------------------------------------------------------------
Top 10 packages in code area:                               Top 10 object types in image heap:
   2.44MB com.sun.tools.javac.comp                             5.00MB byte[] for code metadata
   1.56MB sun.security.ssl                                     2.60MB java.lang.Class
 948.92KB java.util                                            2.51MB java.lang.String
 849.89KB com.sun.tools.javac.code                             2.21MB byte[] for general heap data
 685.28KB com.sun.tools.javac.jvm                              1.87MB byte[] for java.lang.String
 675.29KB com.sun.crypto.provider                           1001.06KB com.oracle.svm.core.hub.DynamicHubCompanion
 473.62KB sun.security.x509                                  534.83KB byte[] for reflection metadata
 470.83KB java.lang                                          504.76KB java.lang.String[]
 426.55KB com.sun.tools.javac.parser                         459.23KB java.util.HashMap$Node
 418.89KB io.netty.buffer                                    384.30KB c.o.svm.core.hub.DynamicHub$ReflectionMetadata
  13.69MB for 312 more packages                                3.40MB for 2390 more object types
------------------------------------------------------------------------------------------------------------------------
                        3.4s (4.2% of total time) in 28 GCs | Peak RSS: 6.14GB | CPU load: 6.40
------------------------------------------------------------------------------------------------------------------------
Produced artifacts:
 /home/paulo/Projects/vertx-howtos/graal-native-image-howto/steps/step-2/target/hello_native (executable)
 /home/paulo/Projects/vertx-howtos/graal-native-image-howto/steps/step-2/target/hello_native.build_artifacts.txt (txt)
========================================================================================================================
Finished generating 'hello_native' in 1m 20s.
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  01:21 min
[INFO] Finished at: 2022-11-29T12:57:27+01:00
[INFO] ------------------------------------------------------------------------

Running the application will be as simple as:

$ ./target/hello_native run vertx.APIClientVerticle
Got HTTP response with status 200 with data Two peanuts were walking down the street. One was a salted.
$ ./target/hello_native run vertx.HTTPServer
Dec 02, 2020 7:51:56 PM io.netty.channel.DefaultChannelId defaultProcessId
WARNING: Failed to find the current process ID from ''; using a random value: 1891971538
Dec 02, 2020 7:51:56 PM io.vertx.core.impl.launcher.commands.VertxIsolatedDeployer
INFO: Succeeded in deploying verticle
Server listening on http://localhost:8080/
$ ./target/hello_native run vertx.HTTPSServer
Dec 02, 2020 7:56:25 PM io.netty.channel.DefaultChannelId defaultProcessId
WARNING: Failed to find the current process ID from ''; using a random value: -1125265761
Dec 02, 2020 7:56:25 PM io.vertx.core.impl.launcher.commands.VertxIsolatedDeployer
INFO: Succeeded in deploying verticle
Server listening on https://localhost:8443/
If you’re interested in knowing the RAM usage just execute: ps x -o pid,rss,command|grep hello_native
      and you will observe something like: 59751 35484 ./target/hello_native run vertx.HTTPVerticle About 36MB
$ ./target/hello_native run vertx.HTTPVerticle -instances 4
Server listening on http://localhost:8080/
Server listening on http://localhost:8080/
Server listening on http://localhost:8080/
Server listening on http://localhost:8080/

And this concludes the native image howto.

The full source of this howto can be found here