我可以在原生构建中将 Kotlin Arrow-lib 与 Quarkus 一起使用吗

问题描述

我开始了一个新的 Kotlin 项目,我想将 arrow-kt core Lib 与 Quarkus (1.12.2) 结合使用。我想在 GraalVM 中使用 Quarkus 的本地编译功能。我的第一个想法是箭头是一个没有反射的简单库,但后来我读了 that。 由于 GraalVm 在运行时在本机可执行文件中存在反射问题,这会是 Arrow 的问题吗?如果是问题,我可以通过简单地避开 Arrow 的某些功能来绕过问题吗?

我知道我可以在 Quarkus/GraalVM 中标记类进行反射。 通过反射检查哪些类?我可以简单地为几个类添加反射信息,还是需要为整个库或我的整个代码添加反射信息?

解决方法

正如 another answer 所述,较新的版本可能不使用反射,因此有关特定库的问题并不那么重要。不过,为了完整起见,以下是对这些问题的一般回答。

由于 GraalVm 在本地可执行文件中存在反射问题 运行时,这会是 Arrow 的问题吗?

GraalVM 本机映像在从程序中构建可执行文件期间使用静态分析。这意味着语言的动态特性需要显式配置以帮助分析将必要的类/方法包含到二进制文件中。例如,静态分析无法预测哪些类将通过反射访问或代理,当这些类仅通过字符串引用时,有时只能在运行时构造。

我可以简单地为几个类添加反射信息,还是需要为整个库或我的整个代码添加反射信息?

您确实需要通过反射 API 配置所有访问。这些库可以为它们使用反射、资源等提供配置。但是如果它们需要对您的应用程序类进行反射访问,那么它们就不能这样做。

所需的配置是 json 文件的形式,例如包含类的反射配置可能如下所示:

[
  {
    "name" : "java.lang.String","fields" : [
      { "name" : "value","allowWrite" : true },{ "name" : "hash" }
    ],"methods" : [
      { "name" : "<init>","parameterTypes" : [] },{ "name" : "<init>","parameterTypes" : ["char[]"] },{ "name" : "charAt" },{ "name" : "format","parameterTypes" : ["java.lang.String","java.lang.Object[]"] }
    ]
  }
]

上面的示例指定程序希望能够反射性地使用 java.lang.String,可以访问字段 valuehash 以及列出的方法。

创建这样的配置可能有点乏味,但相当简单。一些框架通过提供注释来标记类,然后自己生成配置来帮助您。

但是如果要为不知道的库创建配置,手动创建配置比较困难,可以使用,推荐使用assisted configuration agent

这意味着您执行您的程序启用一个 javaagent,它将跟踪和记录所有必要功能的配置:资源访问、序列化/反序列化、代理、JNI、反射等。

所以你像这样运行应用程序并执行你感兴趣的代码路径(可能通过你的测试),输出目录将包含配置。

java -agentlib:native-image-agent=config-output-dir=/path/to/config-dir/ -jar myjar.jar

然后,如果需要,您可以手动编辑配置,例如,推断您没有使用跟踪代理运行的代码路径。

然后运行本机映像构建过程并传递配置选项,例如,为反射文件配置指定: -H:ReflectionConfigurationFiles=/path/to/reflectconfig

您还可以使用 META-INF/native-image 目录是配置文件的默认位置这一事实,因此您不必指定选项。例如,如果您在 config/META-INF/native-image 目录中生成配置,那么您可以将其放置在本机映像的类路径中,文件将被自动提取:

native-image -cp config -jar myjar.jar
,

从即将发布的 0.12.0 开始,Arrow 不使用反射。以前,它在访问 bind 类的 ContinuationUtils 操作中对 MonadContinuation 的所有继承者进行了 monad 理解。在这个类中,我们使用反射来读取和写入与延续堆栈标签相关的私有字段。