GRAALVM(本机图像)无法编译记录依赖项

发布于 2025-02-10 21:32:15 字数 935 浏览 2 评论 0 原文

我正在使用当前版本的社区版本:graalvm/native-image 22.1.0

的项目对记录框架logback(版本1.2.3)具有依赖性

我 graalvm本地形象抱怨:

错误:java.util.concurrent.executionException: com.oracle.graal.pointsto.constraints.unsupportedfeatureexception:否 图像中允许CH.QOS.LOGBACK.CLASSIC.LOGGER的实例 堆由于该类应在图像运行时初始化。看看如何 该对象有实例化使用 -Trace-Object-Instantiation = CH.QOS.LOGBACK.CLASSIC.LOGGER。

我播放了许多不同的设置排列,例如 - initialize-at-run time = \< logback class \> and and - initialize-at-at-run-完整列表时间

我尝试使用 java -agentlib生成反射配置文件

:native-image-agent = config-out-agent = config-output-dir = meta-inf/native-imimage -jar build-jar build/myjar-all.jar < /code>

并将其添加到配置文件中

-H:ReflectionConfigurationFiles = Reflect-config.json

但没有成功。始终获取不同的错误消息,全部与记录有关。

所以我的问题是:

有人在以前与Graalvm成功编译了Rogback?

I'm using the current version of community edition: GraalVM/native-image 22.1.0

My project has a dependency to the logging framework logback (version 1.2.3)

If I want to compile my "all-in-one" jar with graalVM the native-image complains:

Error: java.util.concurrent.ExecutionException:
com.oracle.graal.pointsto.constraints.UnsupportedFeatureException: No
instances of ch.qos.logback.classic.Logger are allowed in the image
heap as this class should be initialized at image runtime. To see how
this object got instantiated use
--trace-object-instantiation=ch.qos.logback.classic.Logger.

I played around with many different permutations of settings e.g. --initialize-at-run-time=\<complete list of logback classes\> and --initialize-at-run-time

I tried to generate a reflection configuration file with

java -agentlib:native-image-agent=config-output-dir=META-INF/native-image -jar build/myjar-all.jar

and added it to the config file with

-H:ReflectionConfigurationFiles=reflect-config.json

But without success. Always getting different error messages all related to logback.

So my question:

Has anyone got logback successfully compiled with graalvm before?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

人生戏 2025-02-17 21:32:15

简短答案 - 您应该将 ch.qos.logback 添加到 - initialize-at-at-at-at-at-at-at-time

--initialize-at-build-time=ch.qos.logback

有关详细信息,我想发布我所做的工作来制作 logback 与Graalvm一起工作。

build.gradle 文件中,我添加了有关在构建时间,运行时以及文件路径中应包含的内容的指令,其中包含反射配置:

graalvmNative {
  binaries {
    all {
      resources.autodetect()
    }
    main {
      imageName.set('app') 
      buildArgs.add('--verbose')
      buildArgs.add('--add-opens=java.base/java.nio=ALL-UNNAMED')
      buildArgs.add('--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED')
      buildArgs.add('--add-opens=java.base/jdk.internal.ref=ALL-UNNAMED')
      buildArgs.add('--trace-class-initialization=ch.qos.logback.classic.Logger')
      buildArgs.add('--trace-object-instantiation=ch.qos.logback.core.AsyncAppenderBase$Worker')
      buildArgs.add('--initialize-at-build-time=org.slf4j.LoggerFactory,ch.qos.logback')
      buildArgs.add('--initialize-at-run-time=io.netty')
    }
  }
}

nativeBuild {
  buildArgs('-H:ReflectionConfigurationFiles=../../../src/main/resources/reflection-config.json')
}

这是 reflection-config的内容.json 文件:

[
  {
    "name": "ch.qos.logback.classic.AsyncAppender",
    "allDeclaredConstructors": true,
    "allPublicConstructors": true,
    "allDeclaredMethods": true,
    "allPublicMethods": true,
    "allDeclaredFields": true,
    "allPublicFields": true,
    "allDeclaredClasses": true,
    "allPublicClasses": true
  },
  {
    "name": "ch.qos.logback.classic.encoder.PatternLayoutEncoder",
    "allDeclaredConstructors": true,
    "allPublicConstructors": true,
    "allDeclaredMethods": true,
    "allPublicMethods": true,
    "allDeclaredFields": true,
    "allPublicFields": true,
    "allDeclaredClasses": true,
    "allPublicClasses": true
  },
  {
    "name": "ch.qos.logback.classic.pattern.DateConverter",
    "allDeclaredConstructors": true,
    "allPublicConstructors": true,
    "allDeclaredMethods": true,
    "allPublicMethods": true,
    "allDeclaredFields": true,
    "allPublicFields": true,
    "allDeclaredClasses": true,
    "allPublicClasses": true
  },
  {
    "name": "ch.qos.logback.classic.pattern.LevelConverter",
    "allDeclaredConstructors": true,
    "allPublicConstructors": true,
    "allDeclaredMethods": true,
    "allPublicMethods": true,
    "allDeclaredFields": true,
    "allPublicFields": true,
    "allDeclaredClasses": true,
    "allPublicClasses": true
  },
  {
    "name": "ch.qos.logback.classic.pattern.LineSeparatorConverter",
    "allDeclaredConstructors": true,
    "allPublicConstructors": true,
    "allDeclaredMethods": true,
    "allPublicMethods": true,
    "allDeclaredFields": true,
    "allPublicFields": true,
    "allDeclaredClasses": true,
    "allPublicClasses": true
  },
  {
    "name": "ch.qos.logback.classic.pattern.LoggerConverter",
    "allDeclaredConstructors": true,
    "allPublicConstructors": true,
    "allDeclaredMethods": true,
    "allPublicMethods": true,
    "allDeclaredFields": true,
    "allPublicFields": true,
    "allDeclaredClasses": true,
    "allPublicClasses": true
  },
  {
    "name": "ch.qos.logback.classic.pattern.MessageConverter",
    "allDeclaredConstructors": true,
    "allPublicConstructors": true,
    "allDeclaredMethods": true,
    "allPublicMethods": true,
    "allDeclaredFields": true,
    "allPublicFields": true,
    "allDeclaredClasses": true,
    "allPublicClasses": true
  },
  {
    "name": "ch.qos.logback.classic.pattern.ThreadConverter",
    "allDeclaredConstructors": true,
    "allPublicConstructors": true,
    "allDeclaredMethods": true,
    "allPublicMethods": true,
    "allDeclaredFields": true,
    "allPublicFields": true,
    "allDeclaredClasses": true,
    "allPublicClasses": true
  },
  {
    "name": "ch.qos.logback.core.ConsoleAppender",
    "allDeclaredConstructors": true,
    "allPublicConstructors": true,
    "allDeclaredMethods": true,
    "allPublicMethods": true,
    "allDeclaredFields": true,
    "allPublicFields": true,
    "allDeclaredClasses": true,
    "allPublicClasses": true
  },
  {
    "name": "ch.qos.logback.core.FileAppender",
    "allDeclaredConstructors": true,
    "allPublicConstructors": true,
    "allDeclaredMethods": true,
    "allPublicMethods": true,
    "allDeclaredFields": true,
    "allPublicFields": true,
    "allDeclaredClasses": true,
    "allPublicClasses": true
  }
]

我使用此 logback.xml 文件:

<configuration scan="true" scanPeriod="150 seconds">
  <property name="LOG_DIR" value="logs" />

  <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender" target="System.out">
    <encoder>
      <charset>UTF-8</charset>
      <pattern>%d{"yyyy-MM-dd'T'HH:mm:ss.SSSXXX", UTC} {%thread} [%-5level] %logger{0} - %msg%n</pattern>
    </encoder>
  </appender>

  <appender name="FILE" class="ch.qos.logback.core.FileAppender">
    <file>${LOG_DIR}/app.log</file>
    <encoder>
      <charset>UTF-8</charset>
      <pattern>%d{"yyyy-MM-dd'T'HH:mm:ss.SSSXXX", UTC} {%thread} [%-5level] %logger - %msg%n</pattern>
    </encoder>
  </appender>

  <appender name="ASYNC_CONSOLE" class="ch.qos.logback.classic.AsyncAppender">
    <discardingThreshold>0</discardingThreshold> <!-- default 20, means drop lower event when has 20% capacity remaining -->
    <appender-ref ref="CONSOLE" />
    <queueSize>1024</queueSize> <!-- default 256 -->
    <includeCallerData>false</includeCallerData> <!-- default false -->
    <neverBlock>false</neverBlock> <!-- default false, set to true to cause the Appender not block the application and just drop the messages -->
  </appender>

  <appender name="ASYNC_FILE" class="ch.qos.logback.classic.AsyncAppender">
    <discardingThreshold>0</discardingThreshold> <!-- default 20, means drop lower event when has 20% capacity remaining -->
    <appender-ref ref="FILE" />
    <queueSize>1024</queueSize> <!-- default 256 -->
    <includeCallerData>false</includeCallerData> <!-- default false -->
    <neverBlock>false</neverBlock> <!-- default false, set to true to cause the Appender not block the application and just drop the messages -->
  </appender>

  <root level="all">
    <appender-ref ref="ASYNC_CONSOLE" />
    <appender-ref ref="ASYNC_FILE" />
  </root>
</configuration>

Short answer - you should add ch.qos.logback to --initialize-at-build-time:

--initialize-at-build-time=ch.qos.logback

For details, I would like to post what I have done to make logback working with GraalVM.

In the build.gradle file, I added instructions about what should be included at build time, at run time and also path to the file contains reflection configuration:

graalvmNative {
  binaries {
    all {
      resources.autodetect()
    }
    main {
      imageName.set('app') 
      buildArgs.add('--verbose')
      buildArgs.add('--add-opens=java.base/java.nio=ALL-UNNAMED')
      buildArgs.add('--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED')
      buildArgs.add('--add-opens=java.base/jdk.internal.ref=ALL-UNNAMED')
      buildArgs.add('--trace-class-initialization=ch.qos.logback.classic.Logger')
      buildArgs.add('--trace-object-instantiation=ch.qos.logback.core.AsyncAppenderBase$Worker')
      buildArgs.add('--initialize-at-build-time=org.slf4j.LoggerFactory,ch.qos.logback')
      buildArgs.add('--initialize-at-run-time=io.netty')
    }
  }
}

nativeBuild {
  buildArgs('-H:ReflectionConfigurationFiles=../../../src/main/resources/reflection-config.json')
}

Here is the content of reflection-config.json file:

[
  {
    "name": "ch.qos.logback.classic.AsyncAppender",
    "allDeclaredConstructors": true,
    "allPublicConstructors": true,
    "allDeclaredMethods": true,
    "allPublicMethods": true,
    "allDeclaredFields": true,
    "allPublicFields": true,
    "allDeclaredClasses": true,
    "allPublicClasses": true
  },
  {
    "name": "ch.qos.logback.classic.encoder.PatternLayoutEncoder",
    "allDeclaredConstructors": true,
    "allPublicConstructors": true,
    "allDeclaredMethods": true,
    "allPublicMethods": true,
    "allDeclaredFields": true,
    "allPublicFields": true,
    "allDeclaredClasses": true,
    "allPublicClasses": true
  },
  {
    "name": "ch.qos.logback.classic.pattern.DateConverter",
    "allDeclaredConstructors": true,
    "allPublicConstructors": true,
    "allDeclaredMethods": true,
    "allPublicMethods": true,
    "allDeclaredFields": true,
    "allPublicFields": true,
    "allDeclaredClasses": true,
    "allPublicClasses": true
  },
  {
    "name": "ch.qos.logback.classic.pattern.LevelConverter",
    "allDeclaredConstructors": true,
    "allPublicConstructors": true,
    "allDeclaredMethods": true,
    "allPublicMethods": true,
    "allDeclaredFields": true,
    "allPublicFields": true,
    "allDeclaredClasses": true,
    "allPublicClasses": true
  },
  {
    "name": "ch.qos.logback.classic.pattern.LineSeparatorConverter",
    "allDeclaredConstructors": true,
    "allPublicConstructors": true,
    "allDeclaredMethods": true,
    "allPublicMethods": true,
    "allDeclaredFields": true,
    "allPublicFields": true,
    "allDeclaredClasses": true,
    "allPublicClasses": true
  },
  {
    "name": "ch.qos.logback.classic.pattern.LoggerConverter",
    "allDeclaredConstructors": true,
    "allPublicConstructors": true,
    "allDeclaredMethods": true,
    "allPublicMethods": true,
    "allDeclaredFields": true,
    "allPublicFields": true,
    "allDeclaredClasses": true,
    "allPublicClasses": true
  },
  {
    "name": "ch.qos.logback.classic.pattern.MessageConverter",
    "allDeclaredConstructors": true,
    "allPublicConstructors": true,
    "allDeclaredMethods": true,
    "allPublicMethods": true,
    "allDeclaredFields": true,
    "allPublicFields": true,
    "allDeclaredClasses": true,
    "allPublicClasses": true
  },
  {
    "name": "ch.qos.logback.classic.pattern.ThreadConverter",
    "allDeclaredConstructors": true,
    "allPublicConstructors": true,
    "allDeclaredMethods": true,
    "allPublicMethods": true,
    "allDeclaredFields": true,
    "allPublicFields": true,
    "allDeclaredClasses": true,
    "allPublicClasses": true
  },
  {
    "name": "ch.qos.logback.core.ConsoleAppender",
    "allDeclaredConstructors": true,
    "allPublicConstructors": true,
    "allDeclaredMethods": true,
    "allPublicMethods": true,
    "allDeclaredFields": true,
    "allPublicFields": true,
    "allDeclaredClasses": true,
    "allPublicClasses": true
  },
  {
    "name": "ch.qos.logback.core.FileAppender",
    "allDeclaredConstructors": true,
    "allPublicConstructors": true,
    "allDeclaredMethods": true,
    "allPublicMethods": true,
    "allDeclaredFields": true,
    "allPublicFields": true,
    "allDeclaredClasses": true,
    "allPublicClasses": true
  }
]

I use this logback.xml file:

<configuration scan="true" scanPeriod="150 seconds">
  <property name="LOG_DIR" value="logs" />

  <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender" target="System.out">
    <encoder>
      <charset>UTF-8</charset>
      <pattern>%d{"yyyy-MM-dd'T'HH:mm:ss.SSSXXX", UTC} {%thread} [%-5level] %logger{0} - %msg%n</pattern>
    </encoder>
  </appender>

  <appender name="FILE" class="ch.qos.logback.core.FileAppender">
    <file>${LOG_DIR}/app.log</file>
    <encoder>
      <charset>UTF-8</charset>
      <pattern>%d{"yyyy-MM-dd'T'HH:mm:ss.SSSXXX", UTC} {%thread} [%-5level] %logger - %msg%n</pattern>
    </encoder>
  </appender>

  <appender name="ASYNC_CONSOLE" class="ch.qos.logback.classic.AsyncAppender">
    <discardingThreshold>0</discardingThreshold> <!-- default 20, means drop lower event when has 20% capacity remaining -->
    <appender-ref ref="CONSOLE" />
    <queueSize>1024</queueSize> <!-- default 256 -->
    <includeCallerData>false</includeCallerData> <!-- default false -->
    <neverBlock>false</neverBlock> <!-- default false, set to true to cause the Appender not block the application and just drop the messages -->
  </appender>

  <appender name="ASYNC_FILE" class="ch.qos.logback.classic.AsyncAppender">
    <discardingThreshold>0</discardingThreshold> <!-- default 20, means drop lower event when has 20% capacity remaining -->
    <appender-ref ref="FILE" />
    <queueSize>1024</queueSize> <!-- default 256 -->
    <includeCallerData>false</includeCallerData> <!-- default false -->
    <neverBlock>false</neverBlock> <!-- default false, set to true to cause the Appender not block the application and just drop the messages -->
  </appender>

  <root level="all">
    <appender-ref ref="ASYNC_CONSOLE" />
    <appender-ref ref="ASYNC_FILE" />
  </root>
</configuration>
迟到的我 2025-02-17 21:32:15

也许我迟到了回答,但这可能会对某人有所帮助。我还面临着 logback.xml 初始化的问题。

在搜索解决方案时,我发现Spring建议将文件命名为 logback-spring.xml 而不是 logback.xml

请参阅此处

Maybe I am late to answer but this may help someone. I was also facing issues with logback.xml initialisation.

While searching for solution I found that spring suggests to name the file as logback-spring.xml instead of logback.xml

See here https://docs.spring.io/spring-boot/docs/2.1.13.RELEASE/reference/html/boot-features-logging.html

enter image description here

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文