GraalVM 本机图像反射不起作用
GraalVM native image reflection doesn't work
我正在尝试使用 maven 插件创建 GraalVM 本机映像,但遇到了一些问题。
Here the config for the maven plugin
我正在使用 GraalVM JDK(通过 Sdkman 安装):
$ java -version
openjdk version "16.0.1" 2021-04-20
OpenJDK Runtime Environment GraalVM CE 21.1.0 (build 16.0.1+9-jvmci-21.1-b05)
OpenJDK 64-Bit Server VM GraalVM CE 21.1.0 (build 16.0.1+9-jvmci-21.1-b05, mixed mode, sharing)
我已经完成了一个简单的主要 class 喜欢:
package it.r;
public class Main {
public static void main(String[] args) {
System.out.println("********");
System.out.println(Main.class.getConstructors().length);
System.out.println("********");
}
}
当使用 mvn exec:java -Dexec.mainClass=it.r.Main
执行它时,我得到的结果是:
********
1
********
但是在执行 mvn package
然后执行创建的可执行文件时,结果是:
********
0
********
为什么会这样?
Here the git repo to reproduce
这个问题似乎影响了 Jackson 的反序列化,因为在另一个例子中我有一个来自 jackson 的错误,它无法反序列化 yaml 文件,因为它找不到我的 class.
的构造函数
类 使用反射需要注册才能将它们包含在构建的本机图像中,more info in the docs
当 GraalVM 本机映像将您的应用程序构建为本机二进制文件时,它静态 分析您的应用程序。
分析是静态的,因此您的应用程序可能使用的几个动态功能需要显式配置,例如:
- 反思
- 序列化
- 方法句柄
- 使用资源(例如
classloader.getResource()
)
- JNI
此显式配置作为 json 配置文件提供,例如,
您可以手动提供配置文件,但您也可以 运行 您的应用程序使用 javaagent which will record usages of features requiring configuration。
简而言之,您 运行 您的应用程序是这样的:
java -agentlib:native-image-agent=config-output-dir=/path/to/config-dir/
和练习使用您要配置的代码的代码路径。这很重要,因为跟踪代理只能记录它实际看到的代码的配置 运行ning.
然后输出目录将包含一个 json 文件,例如如下所示:
[
{
"name":"StringCapitalizer",
"methods":[{"name":"capitalize","parameterTypes":["java.lang.String"] }]
},
{
"name":"StringReverser",
"methods":[{"name":"reverse","parameterTypes":["java.lang.String"] }]
}
该文件列出了需要包含在分析中的类和二进制结果及其需要访问的成员。
手动创建相当简单,但有点乏味,这就是首选代理方法的原因。
还有一个 programmatic way to configure classes and members be registered for reflection,但使用它意味着您需要将对 GraalVM 代码的依赖项包含到您的应用程序中。
我正在尝试使用 maven 插件创建 GraalVM 本机映像,但遇到了一些问题。
Here the config for the maven plugin
我正在使用 GraalVM JDK(通过 Sdkman 安装):
$ java -version
openjdk version "16.0.1" 2021-04-20
OpenJDK Runtime Environment GraalVM CE 21.1.0 (build 16.0.1+9-jvmci-21.1-b05)
OpenJDK 64-Bit Server VM GraalVM CE 21.1.0 (build 16.0.1+9-jvmci-21.1-b05, mixed mode, sharing)
我已经完成了一个简单的主要 class 喜欢:
package it.r;
public class Main {
public static void main(String[] args) {
System.out.println("********");
System.out.println(Main.class.getConstructors().length);
System.out.println("********");
}
}
当使用 mvn exec:java -Dexec.mainClass=it.r.Main
执行它时,我得到的结果是:
********
1
********
但是在执行 mvn package
然后执行创建的可执行文件时,结果是:
********
0
********
为什么会这样?
Here the git repo to reproduce
这个问题似乎影响了 Jackson 的反序列化,因为在另一个例子中我有一个来自 jackson 的错误,它无法反序列化 yaml 文件,因为它找不到我的 class.
的构造函数类 使用反射需要注册才能将它们包含在构建的本机图像中,more info in the docs
当 GraalVM 本机映像将您的应用程序构建为本机二进制文件时,它静态 分析您的应用程序。
分析是静态的,因此您的应用程序可能使用的几个动态功能需要显式配置,例如:
- 反思
- 序列化
- 方法句柄
- 使用资源(例如
classloader.getResource()
) - JNI
此显式配置作为 json 配置文件提供,例如,
您可以手动提供配置文件,但您也可以 运行 您的应用程序使用 javaagent which will record usages of features requiring configuration。
简而言之,您 运行 您的应用程序是这样的:
java -agentlib:native-image-agent=config-output-dir=/path/to/config-dir/
和练习使用您要配置的代码的代码路径。这很重要,因为跟踪代理只能记录它实际看到的代码的配置 运行ning.
然后输出目录将包含一个 json 文件,例如如下所示:
[
{
"name":"StringCapitalizer",
"methods":[{"name":"capitalize","parameterTypes":["java.lang.String"] }]
},
{
"name":"StringReverser",
"methods":[{"name":"reverse","parameterTypes":["java.lang.String"] }]
}
该文件列出了需要包含在分析中的类和二进制结果及其需要访问的成员。 手动创建相当简单,但有点乏味,这就是首选代理方法的原因。
还有一个 programmatic way to configure classes and members be registered for reflection,但使用它意味着您需要将对 GraalVM 代码的依赖项包含到您的应用程序中。