◀返回
排查原生镜像运行时错误
成功的提前编译仍然可能生成在运行时崩溃或行为与 Java VM 上应用程序行为不同的镜像。在本指南中,展示了一些导致这种情况的原因,以及诊断和解决问题的方法。
请注意,有时升级到最新版本的 GraalVM 就可以解决问题。
1. 诊断缺少元数据注册
首先诊断是否有任何元数据配置缺失。原生镜像需要在构建期间知道所有使用的类。静态分析试图预测应用程序的运行时行为。在某些情况下,您需要向分析提供配置,使其能够看到所有动态功能调用。如果这样做,会导致镜像在应用程序中使用动态功能时在运行时终止,并出现难以诊断的错误。通过尽早检查缺少的元数据可以避免这种情况。
-
将
--exact-reachablity-metadata
选项传递给native-image
工具,并重新构建应用程序。如果您只想对特定包执行此操作,请指定包前缀--exact-reachablity-metadata=[package prefix]
。此选项是在 GraalVM for JDK 23 中引入的,将在下一个功能版本中成为默认选项。它等效于
-H:ThrowMissingRegistrationErrors=
主机选项。 -
接下来运行该原生可执行文件,传递
-XX:MissingRegistrationReportingMode=Warn
选项,查找代码中出现缺少注册的所有位置。 -
如果报告了缺少的元数据,请确保将其添加到 reachability-metadata.json 文件中。请参阅 可达性元数据文档 中的说明。
-
然后使用
-XX:MissingRegistrationReportingMode=Exit
重新启动原生可执行文件,以检测应用程序意外忽略缺少的注册错误(使用catch (Throwable t)
块)的位置。应用程序将无条件地打印包含堆栈跟踪的错误消息,并立即退出。此行为非常适合运行应用程序测试,以确保所有元数据都已包含。
共享库
为了诊断使用原生镜像构建的共享库,您可以:
- 在构建原生共享库时指定
-R:MissingRegistrationReportingMode=Exit
; - 或者在创建隔离区时指定
-XX:MissingRegistrationReportingMode=Exit
。graal_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.util
和 java.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
选项,以启用对类初始化、替换等的诊断输出。