├── pom.xml └── src └── main └── java └── vertx └── APIClientVerticle.java └── HTTPVerticle.java └── HTTPSVerticle.java
本操作指南展示了使用 GraalVM 构建 Vert.x 本机镜像所需的所有当前步骤和变通方法。
您将编写一个多 Verticle 应用程序(客户端 + 服务器)。
代码将涵盖安全性(SSL)。
借助 GraalVM,代码将被编译为本机代码。
文本编辑器或 IDE
GraalVM (22.3.0)
Maven
本机镜像是将 Java 应用程序优化转换为特定于操作系统/CPU 的本机代码。这个新应用程序将具有与传统 JVM 应用程序不同的特性,其中最显著的特点是
更快的启动时间
(通常)更小的堆大小
因此,本机镜像非常适合 CLI 或 无服务器 应用程序,但没有什么能阻止其也用于服务器应用程序。
本机镜像编译有几个限制(设计使然),其中大部分不适用于 Vert.x 核心代码。这使得 Vert.x 成为编写本机镜像的绝佳选择。然而,有一些已知的限制,可以很容易地通过变通方法来构建本机镜像。
本操作指南将涵盖这些限制,并解释如何使一个简单的 Vert.x 应用程序成为本机应用程序。
首先创建一个遵循以下结构的新项目
├── pom.xml └── src └── main └── java └── vertx └── APIClientVerticle.java └── HTTPVerticle.java └── HTTPSVerticle.java
之后,我们来回顾一下项目的重要部分。以下是您应该使用的 pom.xml
文件的内容
<?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>
这是一个最小的 Hello World
项目。您可以阅读代码来确认这一点
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 https://:8080/");
} else {
listen.cause().printStackTrace();
System.exit(1);
}
});
}
}
到目前为止,没有什么新东西。它是一个普通的 Vert.x Java 项目。
同样适用于其余源代码(稍后将介绍)。
为了构建本机镜像,我们应该添加 native-image-maven-plugin
<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>
我们包含的插件应与已安装的 GraalVM 版本匹配。
指定镜像的最终名称(可执行文件的名称)
主启动类
传递给编译器的参数(在这种情况下,我们希望在出现问题时获得一些调试信息)。
构建镜像现在就像
mvn package
然而,由于声明的主类中没有 public static void main
方法,这将失败。我们可以通过将其添加到 HTTPVerticle
来解决此问题
public static void main(String[] args) {
Vertx.vertx().deployVerticle(new HTTPVerticle());
}
或者配置 GraalVM 的反射配置,使其不排除我们的 Verticle
[
{
"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
}
]
添加对 SSL 的支持并不困难,但需要一些更新。原因是安全库会显著增加最终二进制文件的大小,因此所有安全功能都通过标志禁用。还有其他注意事项,例如允许使用 Java 密钥库,但 必须是 PKCS12
格式,这是 Java9 以来的新默认格式,但在 Java8(GraalVM 基于此版本)中不是。
您现在将向您的项目添加一个 HTTPS Verticle 服务器,在 vertx
包中现有类旁边创建 HTTPSVerticle
类
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://:8443/");
} else {
listen.cause().printStackTrace();
System.exit(1);
}
});
}
}
为此服务器启用 HTTPS。
指定从何处加载证书。
密钥库密码是什么(您不应该这样做,您应该从配置中获取密码,但为了简单起见,这里是硬编码的)。
您需要一个证书,因此这是所需的步骤
# Generate the self signed test certificate $ keytool -genkey \ -alias vertx \ -keypass localhost \ -keystore certificates.keystore \ -storepass localhost \ -keyalg RSA # Convert to PCKS12 $ keytool \ -importkeystore \ -srckeystore certificates.keystore \ -destkeystore certificates.keystore \ -deststoretype pkcs12
如果您构建镜像,它将编译成功,但在运行时无法工作。还需要一件事
启用要添加到本机镜像的安全功能
要启用安全功能,必须将 graal plugin
配置为
<configuration>
<imageName>${project.name}</imageName>
<mainClass>${vertx.verticle}</mainClass>
<buildArgs>--enable-all-security-services</buildArgs>
</configuration>
既然我们已经涵盖了基本的 SSL 安全性,我们就可以接触客户端了。在这个例子中,我们将使用一个简单的 HTTPS API。
package vertx;
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();
});
}
}
这个客户端将发出一个 HTTPS 请求,并将输出打印到控制台。
此时,您应该有一个基本的应用程序,并且您的 pom.xml
应该看起来像
<?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>
运行 mvn clean package
将导致构建失败。目前,由于 vertx-core 仍然依赖于比 4.1.53 更旧的 netty
版本,我们需要手动导入上游添加的配置。这意味着我们需要添加一个新文件
├── pom.xml └── src └── main └── resources └── META-INF/native-image/com.example/myapp └── native-image.properties
这个文件是需要传递给编译器的配置。目前文件相当大,但一旦 Vert.x 核心使用最新的 Netty,其中许多条目就可以删除,只列出 Vert.x 特定的条目。
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
运行编译将是
$ 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] ------------------------------------------------------------------------
运行应用程序将像
$ ./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. ^C $ ./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 https://:8080/ ^C $ ./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://:8443/ ^C
注意
|
如果您有兴趣了解内存使用情况,只需执行:ps x -o pid,rss,command|grep hello_native ,您将看到类似以下内容:59751 35484 ./target/hello_native run vertx.HTTPVerticle 大约 36MB |
您现在已将所有 Verticle 放在同一个镜像中。请记住,您现在可以使用启动器执行所有操作,例如为 HTTP 服务器扩展 Verticle 的数量
$ ./target/hello_native run vertx.HTTPVerticle -instances 4 Server listening on https://:8080/ Server listening on https://:8080/ Server listening on https://:8080/ Server listening on https://:8080/ ^C
至此,本机镜像操作指南结束。
本操作指南的完整源代码可在 此处 找到
我们编写了一个 HTTP 服务器 Verticle。
我们添加了构建镜像所需的元数据。
我们编写了一个 HTTPS 服务器 Verticle。
我们添加了构建镜像所需的安全 DLL 和配置。
我们编写了一个 HTTPS 客户端 Verticle。
我们通过指定类的加载顺序处理了一个构建问题。
我们配置了反射和资源,以便在一个镜像中拥有多个 Verticle。
最后发布:2025-02-05 00:57:02 +0000。