返回

排查原生镜像运行时错误

成功的提前编译仍然可能生成在运行时崩溃或行为与 Java VM 上应用程序行为不同的镜像。在本指南中,展示了一些导致这种情况的原因,以及诊断和解决问题的方法。

请注意,有时升级到最新版本的 GraalVM 就可以解决问题。

1. 诊断缺少元数据注册

首先诊断是否有任何元数据配置缺失。原生镜像需要在构建期间知道所有使用的类。静态分析试图预测应用程序的运行时行为。在某些情况下,您需要向分析提供配置,使其能够看到所有动态功能调用。如果这样做,会导致镜像在应用程序中使用动态功能时在运行时终止,并出现难以诊断的错误。通过尽早检查缺少的元数据可以避免这种情况。

  1. --exact-reachablity-metadata 选项传递给 native-image 工具,并重新构建应用程序。如果您只想对特定包执行此操作,请指定包前缀 --exact-reachablity-metadata=[package prefix]

    此选项是在 GraalVM for JDK 23 中引入的,将在下一个功能版本中成为默认选项。它等效于 -H:ThrowMissingRegistrationErrors= 主机选项。

  2. 接下来运行该原生可执行文件,传递 -XX:MissingRegistrationReportingMode=Warn 选项,查找代码中出现缺少注册的所有位置。

  3. 如果报告了缺少的元数据,请确保将其添加到 reachability-metadata.json 文件中。请参阅 可达性元数据文档 中的说明。

  4. 然后使用 -XX:MissingRegistrationReportingMode=Exit 重新启动原生可执行文件,以检测应用程序意外忽略缺少的注册错误(使用 catch (Throwable t) 块)的位置。应用程序将无条件地打印包含堆栈跟踪的错误消息,并立即退出。此行为非常适合运行应用程序测试,以确保所有元数据都已包含。

共享库

为了诊断使用原生镜像构建的共享库,您可以:

  • 在构建原生共享库时指定 -R:MissingRegistrationReportingMode=Exit
  • 或者在创建隔离区时指定 -XX:MissingRegistrationReportingMode=Exitgraal_create_isolate_params_t 具有 argc (_reserved_1)argv (_reserved_2) 字段,可用于在运行时传递 C 样式命令行选项。但是请注意,这两个字段目前都不是公共 API。

2. 显式设置 java.home

如果您的应用程序代码使用 java.home 属性,请在运行原生可执行文件时使用 -Djava.home=<path> 显式设置它。否则,System.getProperty("java.home") 调用将返回 null 值。

3. 启用 URL 协议

尝试在构建时按需启用所有 URL 协议:--enable-url-protocols=<protocols>。要仅启用 HTTPS 支持,请传递 --enable-https

4. 启用信号处理

如果您的应用程序使用信号处理或 java.lang.Terminator 退出处理程序,请在构建时提供 --install-exit-handlers 选项。

5. 包含所有字符集和区域设置

其他方便的选项是 -H:+AddAllCharsets,用于添加字符集支持,以及 -H:+IncludeAllLocales,用于预初始化对 java.utiljava.text 包中区域设置敏感行为的支持。在构建时传递这些选项。这可能会增加生成二进制文件的大小。

6. 添加缺少的安全提供程序

如果您的应用程序使用安全提供程序,请尝试通过在构建时传递 -H:AdditionalSecurityProviders=<list-of-providers> 选项来预初始化安全提供程序。以下列出了所有可供选择的 JDK 安全提供程序:sun.security.provider.Sun,sun.security.rsa.SunRsaSign,sun.security.ec.SunEC,sun.security.ssl.SunJSSE,com.sun.crypto.provider.SunJCE,sun.security.jgss.SunProvider,com.sun.security.sasl.Provider,org.jcp.xml.dsig.internal.dom.XMLDSigRI,sun.security.smartcardio.SunPCSC,sun.security.provider.certpath.ldap.JdkLDAP,com.sun.security.sasl.gsskerb.JdkSASL

7. 提交原生镜像运行时问题

仅当您尝试了上述所有建议后,请在 GitHub 上提交 原生镜像运行时问题报告,填写必要的信息。

要收集提交适当且可操作的工单所需的信息,建议在启用诊断模式的情况下运行 native-image 构建。传递 --diagnostics-mode 选项,以启用对类初始化、替换等的诊断输出。

与我们联系