GraalVM Native 打包、运行时异常处理

说明

处理完问题后,需要进行重新打包

部分问题需要打包后,运行 GraalVM Native 二进制时,才能发现与验证修复结果

–initialize-at-run-time

问题

Error: com.oracle.svm.core.util.UserError$UserException: Class initialization of io.netty.handler.codec.compression.ZstdOptions failed. Use the option 

    '--initialize-at-run-time=io.netty.handler.codec.compression.ZstdOptions'

 to explicitly request initialization of this class at run time.
Caused by: com.oracle.svm.core.util.UserError$UserException: Class initialization of io.netty.handler.codec.compression.ZstdOptions failed. Use the option 

    '--initialize-at-run-time=io.netty.handler.codec.compression.ZstdOptions'

解决方案

如果同包下的类比较多,可以直接使用包名

<plugin>
    <groupId>org.graalvm.buildtools</groupId>
    <artifactId>native-maven-plugin</artifactId>
    <configuration>
        <classesDirectory>${project.build.outputDirectory}</classesDirectory>
        <buildArgs>
            <arg>--initialize-at-run-time=io.netty.handler.codec.compression.ZstdOptions</arg>
        </buildArgs>
    </configuration>
</plugin>

–initialize-at-build-time

问题

解决方案

<plugin>
    <groupId>org.graalvm.buildtools</groupId>
    <artifactId>native-maven-plugin</artifactId>
    <configuration>
        <classesDirectory>${project.build.outputDirectory}</classesDirectory>
        <buildArgs>
            <arg>--initialize-at-build-time=ch.qos.logback.classic.Logger</arg>
        </buildArgs>
    </configuration>
</plugin>

Required method “xxx” not found in “xxx”

问题

缺少反射的方法,需要在 src/main/resources/META-INF/native-image/${project.groupId}/${project.artifactId}/reflect-config.json 中添加对应的反射对象、方法、方法参数

Caused by: java.lang.AssertionError: Required method "iterator" not found in "java.lang.Iterable"

解决方案 1:添加缺失方法的反射配置

src/main/resources/META-INF/native-image/${project.groupId}/${project.artifactId}/reflect-config.json

{
  "name" : "java.lang.Iterable",
  "methods" : [ {
    "name" : "iterator",
    "parameterTypes" : [ ]
  } ]
}

解决方案 2:添加所有方法的反射配置

src/main/resources/META-INF/native-image/${project.groupId}/${project.artifactId}/reflect-config.json

  1. allDeclaredMethods:包含该类声明的所有方法(包括私有、保护、包私有、公有)。

  2. allPublicMethods:包含所有公有方法(包括从父类或接口继承的公有方法)。

{
  "name" : "java.lang.Iterable",
  "allDeclaredMethods": true,
  "allPublicMethods": true
}

Required constructor not found in “xxx”

问题

缺少反射的构造器,需要在 src/main/resources/META-INF/native-image/${project.groupId}/${project.artifactId}/reflect-config.json 中添加对应的反射对象、方法、方法参数

Caused by: java.lang.AssertionError: Required constructor not found in "java.lang.StringBuilder"

解决方案 1:添加缺失构造器的反射配置

src/main/resources/META-INF/native-image/${project.groupId}/${project.artifactId}/reflect-config.json

[
  {
    "name" : "java.lang.StringBuilder",
    "methods" : [ {
      "name" : "<init>",
      "parameterTypes" : [ ]
    }, {
      "name" : "<init>",
      "parameterTypes" : [ "java.lang.String" ]
    } ]
  }
]

解决方案 2:添加所有构造器的反射配置

src/main/resources/META-INF/native-image/${project.groupId}/${project.artifactId}/reflect-config.json

[
  {
    "name" : "java.lang.StringBuilder",
    "allDeclaredConstructors": true,
    "allPublicConstructors": true
  }
]

logback-spring.xml

问题

在 GraalVM Native 中,logback-spring.xml 不支持 if

ERROR in ch.qos.logback.core.model.processor.conditional.IfModelHandler - Failed to parse condition [property("LOG_BASH_DIR").equals("")] on line 34 org.codehaus.commons.compiler.CompileException: Line 1, Column 36: A method named "property" is not declared in any enclosing class nor any supertype, nor through a static import

Startup with AOT mode enabled failed

问题

org.springframework.boot.AotInitializerNotFoundException: Startup with AOT mode enabled failed: AOT initializer org.apache.seata.namingserver.NamingserverApplication__ApplicationContextInitializer could not be found

解决方案

Maven 打包参数增加:spring-boot:process-aot

mvn clean package -DskipTests spring-boot:process-aot -Pnative native:compile