Spring Boot 更新log4j JSONTemplateLayout包后出现非法访问错误

jv4diomz  于 2022-12-18  发布在  Spring
关注(0)|答案(1)|浏览(448)

我正在java-17-openjdk上运行一个Sping Boot 应用程序,我使用log4j-layout-template-json包将json日志输出到stdout。
在我将软件包版本从2.17.2更新到2.18.0之前,一切都运行良好,现在每当应用尝试记录一些内容时,我都会得到这些堆栈跟踪:

2022-12-13 10:28:59,028 main ERROR An exception occurred processing Appender Console org.apache.logging.log4j.core.appender.AppenderLoggingException: java.lang.IllegalAccessError: class org.apache.logging.log4j.layout.template.json.JsonTemplateLayout$StringBuilderEncoder tried to access method 'void org.apache.logging.log4j.core.layout.TextEncoderHelper.encodeText(java.nio.charset.CharsetEncoder, java.nio.CharBuffer, java.nio.ByteBuffer, java.lang.StringBuilder, org.apache.logging.log4j.core.layout.ByteBufferDestination)' (org.apache.logging.log4j.layout.template.json.JsonTemplateLayout$StringBuilderEncoder and org.apache.logging.log4j.core.layout.TextEncoderHelper are in unnamed module of loader org.springframework.boot.loader.LaunchedURLClassLoader @76fb509a)
    at org.apache.logging.log4j.core.config.AppenderControl.tryCallAppender(AppenderControl.java:165)
    at org.apache.logging.log4j.core.config.AppenderControl.callAppender0(AppenderControl.java:134)
    at org.apache.logging.log4j.core.config.AppenderControl.callAppenderPreventRecursion(AppenderControl.java:125)
    at org.apache.logging.log4j.core.config.AppenderControl.callAppender(AppenderControl.java:89)
    at org.apache.logging.log4j.core.config.LoggerConfig.callAppenders(LoggerConfig.java:675)
    at org.apache.logging.log4j.core.config.LoggerConfig.processLogEvent(LoggerConfig.java:633)
    at org.apache.logging.log4j.core.config.LoggerConfig.log(LoggerConfig.java:616)
    at org.apache.logging.log4j.core.config.LoggerConfig.log(LoggerConfig.java:552)
    at org.apache.logging.log4j.core.config.AwaitCompletionReliabilityStrategy.log(AwaitCompletionReliabilityStrategy.java:82)
    at org.apache.logging.log4j.core.Logger.log(Logger.java:161)
    at org.apache.logging.log4j.spi.AbstractLogger.tryLogMessage(AbstractLogger.java:2205)
    at org.apache.logging.log4j.spi.AbstractLogger.logMessageTrackRecursion(AbstractLogger.java:2159)
    at org.apache.logging.log4j.spi.AbstractLogger.logMessageSafely(AbstractLogger.java:2142)
    at org.apache.logging.log4j.spi.AbstractLogger.logMessage(AbstractLogger.java:1994)
    at org.apache.logging.log4j.spi.AbstractLogger.logIfEnabled(AbstractLogger.java:1852)
    at org.apache.commons.logging.LogAdapter$Log4jLog.log(LogAdapter.java:270)
    at org.apache.commons.logging.LogAdapter$Log4jLog.info(LogAdapter.java:230)
    at org.springframework.boot.StartupInfoLogger.logStarting(StartupInfoLogger.java:55)
    at org.springframework.boot.SpringApplication.logStartupInfo(SpringApplication.java:618)
    at org.springframework.boot.SpringApplication.prepareContext(SpringApplication.java:377)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:307)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1306)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1295)
    at org.engine.App.main(App.java:40)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:568)
    at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:49)
    at org.springframework.boot.loader.Launcher.launch(Launcher.java:108)
    at org.springframework.boot.loader.Launcher.launch(Launcher.java:58)
    at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:65)
Caused by: java.lang.IllegalAccessError: class org.apache.logging.log4j.layout.template.json.JsonTemplateLayout$StringBuilderEncoder tried to access method 'void org.apache.logging.log4j.core.layout.TextEncoderHelper.encodeText(java.nio.charset.CharsetEncoder, java.nio.CharBuffer, java.nio.ByteBuffer, java.lang.StringBuilder, org.apache.logging.log4j.core.layout.ByteBufferDestination)' (org.apache.logging.log4j.layout.template.json.JsonTemplateLayout$StringBuilderEncoder and org.apache.logging.log4j.core.layout.TextEncoderHelper are in unnamed module of loader org.springframework.boot.loader.LaunchedURLClassLoader @76fb509a)
    at org.apache.logging.log4j.layout.template.json.JsonTemplateLayout$StringBuilderEncoder.encode(JsonTemplateLayout.java:241)
    at org.apache.logging.log4j.layout.template.json.JsonTemplateLayout$StringBuilderEncoder.encode(JsonTemplateLayout.java:216)
    at org.apache.logging.log4j.layout.template.json.JsonTemplateLayout.encode(JsonTemplateLayout.java:304)
    at org.apache.logging.log4j.layout.template.json.JsonTemplateLayout.encode(JsonTemplateLayout.java:58)
    at org.apache.logging.log4j.core.appender.AbstractOutputStreamAppender.directEncodeEvent(AbstractOutputStreamAppender.java:215)
    at org.apache.logging.log4j.core.appender.AbstractOutputStreamAppender.tryAppend(AbstractOutputStreamAppender.java:208)
    at org.apache.logging.log4j.core.appender.AbstractOutputStreamAppender.append(AbstractOutputStreamAppender.java:199)
    at org.apache.logging.log4j.core.config.AppenderControl.tryCallAppender(AppenderControl.java:161)
    ... 31 more

正如你所看到的,这个问题已经发生在spring自己创建的日志上了,更新log4j-layout-template-json到最新版本(2.19.0)并没有解决这个问题。
注意,这只在尝试执行应用的jar文件时出现,而在使用maven和spring-mvc运行surefire和failsafe测试时不会出现。
有关我的java版本的更多详细信息:

$ java --version
openjdk 17.0.5 2022-10-18
OpenJDK Runtime Environment (build 17.0.5+8-Ubuntu-2ubuntu120.04)
OpenJDK 64-Bit Server VM (build 17.0.5+8-Ubuntu-2ubuntu120.04, mixed mode, sharing)

下面是我的pom.xml文件的一个示例:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.7.3</version>
    <relativePath/>
  </parent>

  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
      <exclusions>
        <exclusion>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-tomcat</artifactId>
        </exclusion>
        <exclusion>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-logging</artifactId>
        </exclusion>
      </exclusions>
    </dependency>

    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-log4j2</artifactId>
    </dependency>

    <dependency>
      <groupId>org.apache.logging.log4j</groupId>
      <artifactId>log4j-layout-template-json</artifactId>
      <version>2.18.0</version>
    </dependency>
  </dependencies>


我的log4j配置文件如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration>

    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <JsonTemplateLayout eventTemplateUri="classpath:JSONLogLayout.json"></JsonTemplateLayout>
        </Console>
    </Appenders>
    <Loggers>

        <logger name="org.jooq" level="warn" additivity="false">
            <appender-ref ref="Console" />
        </logger>

        <Root level="info">
            <AppenderRef ref="Console"/>
        </Root>

    </Loggers>
</Configuration>
fjaof16o

fjaof16o1#

spring-boot-starter-parent POM文件管理数百个库版本的版本(参见其父spring-boot-dependencies<dependencyManagement>出现在其中),所有Log4j2工件都在其中。
即使log4j-layout-template-json:2.18.0依赖于log4j-core:2.18.0,Maven也会选择后者的版本2.17.2,从而导致您遇到的版本问题。
为了使所有Log4j2工件具有相同的版本,您需要覆盖spring-boot-dependencies中指定的log4j2.version属性:

<properties>
    <log4j2.version>2.19.0</log4j2.version>
</properties>

从POM文件中删除显式版本。

相关问题