如何使用GraalVM本机映像修复“尝试避免初始化导致初始化的类”

2022-09-03 15:28:15

我正在尝试从胖jar文件创建一个本机映像

$ native-image -H:+TraceClassInitialization --initialize-at-run-time=org.slf4j,org.apache.log4j \
               -jar ./my-jar-with-dependencies.jar

我收到这些错误消息,例如:

错误:应在运行时初始化的类在映像生成期间被初始化:org.apache.log4j.级别 在生成时请求初始化类(从命令行)。org.apache.log4j.Level 已在没有本机映像初始化检测的情况下进行初始化,并且无法跟踪堆栈跟踪。尽量避免初始化导致初始化 org.apache.log4j.Level org.slf4j.log4j12.Log4jLoggerAdapter 在生成时请求初始化类(从命令行)。org.slf4j.log4j12.Log4jLoggerAdapter 已在没有本机映像初始化检测的情况下初始化,并且无法跟踪堆栈跟踪。尽量避免初始化导致初始化 org.slf4j.log4j12.Log4jLoggerAdapter org.apache.log4j.Logger 类在生成时被请求初始化的类(从命令行)。org.apache.log4j.Logger 已在没有本机映像初始化检测的情况下进行初始化,并且无法跟踪堆栈跟踪。尽量避免初始化导致 org.apache.log4j.Logger 初始化的类

解决问题的方式和途径是什么?我该如何处理这些消息?avoiding to initialize the class

我的 graavlVM 版本是 2.0.0-java11


答案 1

这些步骤对我有用。我尝试过使用slf4j和logback,log4j2,但最终有效的是slf4j-simple。基本上,我尝试在 中包含触发初始化的特定类。这就是我的工作。--initialize-at-build-time

  • 在 build 命令上添加参数,如下所示:-H:+TraceClassInitialization
native-image -jar my-app.jar 
-H:IncludeResources=".*.xml|.*.conf" 
-H:+ReportUnsupportedElementsAtRuntime 
-H:+TraceClassInitialization 
-H:Name=my-app
--verbose
  • 运行它,你会看到一些这样的错误:
Error: Classes that should be initialized at run time got initialized during image building:
 org.slf4j.simple.SimpleLogger was unintentionally initialized at build time. io.netty.channel.AbstractChannel caused initialization of this class with the following trace:
        at org.slf4j.simple.SimpleLogger.<clinit>(SimpleLogger.java) // THIS IS THE OFFENDING CLASS
        at org.slf4j.simple.SimpleLoggerFactory.<init>(SimpleLoggerFactory.java:45)
        at org.slf4j.simple.SimpleServiceProvider.initialize(SimpleServiceProvider.java:43)
  • 你看我标记的一行。这是要包含的类。
  • 接下来使用额外的参数运行相同的命令--initialize-at-build-time=org.slf4j.simple.SimpleLogger
  • 运行它。您可能需要重复上述所有步骤,因为可能会出现更多错误。如果是这样,请添加类,用逗号分隔它们。

在我的情况下,最终命令看起来像这样

native-image -jar my-app.jar 
-H:IncludeResources=".*.xml|.*.conf" 
-H:+ReportUnsupportedElementsAtRuntime 
-H:+TraceClassInitialization 
--initialize-at-build-time=org.slf4j.simple.SimpleLogger,org.slf4j.LoggerFactory
-H:Name=my-app
--verbose

答案 2

以下是要排除的类的完整列表,如果您使用的是 Slf4J 和 Logback:

--initialize-at-build-time=\
org.slf4j.impl.StaticLoggerBinder\
,org.slf4j.LoggerFactory\
,ch.qos.logback.classic.Logger\
,ch.qos.logback.core.spi.AppenderAttachableImpl\
,ch.qos.logback.core.status.StatusBase\
,ch.qos.logback.classic.Level\
,ch.qos.logback.core.status.InfoStatus\
,ch.qos.logback.classic.PatternLayout\
,ch.qos.logback.core.CoreConstants

推荐