1

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

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

4

2 回答 2

3

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

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

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

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

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

The configuration required is in the form of json files, for example a reflection configuration to include a class might look like:

[
  {
    "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[]"] }
    ]
  }
]

The example above specifies that the program would like to be able to use java.lang.String reflectively, have access to the fields value and hash and the methods listed.

It might be a bit tedious, however rather straightforward to create config like that. Some frameworks help you by providing annotations to mark classes with and then generate the config themselves.

But if you want to create the config for the library that you don't know, so it's hard to manually create the config, you can use and it's recommended to use the assisted configuration agent.

This means you execute your program enabling a javaagent, which will trace and write down config for all necessary features: resource access, serialization/deserialization, proxies, JNI, reflection, etc.

So you run the application like this and execute the codepaths you're interested in (maybe through your tests) and the output dir will contain the config.

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

You can then edit the config if needed manually to, for example, extrapolate to the code paths you didn't run with the tracing agent.

Then you run the native image build process passing the config options, for example, for the reflection file config specify: -H:ReflectionConfigurationFiles=/path/to/reflectconfig.

You can also use the fact that META-INF/native-image directory is the default location for the configuration files, so you don't have to specify the options. For example if you generate the config in the config/META-INF/native-image directory, then you can place it on the classpath for the native image and the files will be picked up automatically:

native-image -cp config -jar myjar.jar
于 2021-03-27T19:55:01.540 回答
2

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

于 2021-03-26T17:38:35.713 回答