Spring Boot 2.4.0部署Tomcat 8报YAMLFactory不可分配给JsonFactory错误
14:43:28.769 [main] ERROR org.springframework.boot.SpringApplication - Application run failed java.lang.VerifyError: Bad type on operand stack Exception Details: Location: org/apache/logging/log4j/core/config/yaml/YamlConfiguration.getObjectMapper()Lcom/fasterxml/jackson/databind/ObjectMapper; @11: invokespecial Reason: Type 'com/fasterxml/jackson/dataformat/yaml/YAMLFactory' (current frame, stack[2]) is not assignable to 'com/fasterxml/jackson/core/JsonFactory' Current Frame: bci: @11 flags: { } locals: { 'org/apache/logging/log4j/core/config/yaml/YamlConfiguration' } stack: { uninitialized 0, uninitialized 0, 'com/fasterxml/jackson/dataformat/yaml/YAMLFactory' } Bytecode: 0x0000000: bb00 0259 bb00 0359 b700 04b7 0005 b200 0x0000010: 0604 b600 07b0 at org.apache.logging.log4j.core.config.yaml.YamlConfigurationFactory.getConfiguration(YamlConfigurationFactory.java:66) ~[log4j-core-2.13.3.jar:2.13.3] at org.apache.logging.log4j.core.config.ConfigurationFactory$Factory.getConfiguration(ConfigurationFactory.java:572) ~[log4j-core-2.13.3.jar:2.13.3] ... 省略后续调用栈
根本原因
这个错误是Jackson依赖版本不兼容 + Tomcat类加载机制差异共同导致的:
- 从错误信息的
Reason部分可以看出,Log4j2 2.13.3加载yaml配置时,需要将YAMLFactory实例向上转型为父类JsonFactory,但JVM校验发现两个类版本不兼容,无法完成转型。 - 命令行运行Spring Boot jar包时,Spring Boot使用自研类加载器优先加载项目内部的依赖,Jackson版本由Spring Boot 2.4.0统一管控,所有Jackson组件版本完全匹配,因此不会出现冲突。
- 部署到Tomcat时触发问题,是因为Tomcat的类加载默认遵循「父类加载器优先」规则:会先加载
TOMCAT_HOME/lib目录下的公共依赖,再加载Web应用WEB-INF/lib下的私有依赖。如果Tomcat公共lib目录中存在版本不匹配的Jackson jar包,就会出现:YAMLFactory从应用私有依赖加载,而它的父类JsonFactory从Tomcat公共目录的旧版本Jackson中加载,两个类版本不兼容导致转型失败,抛出VerifyError。
修复方案
按优先级可选以下方案:
- 清理Tomcat公共依赖:删除
TOMCAT_HOME/lib目录下所有Jackson相关的jar包,包括jackson-core、jackson-databind、jackson-annotations、jackson-dataformat-yaml,让Web应用自行加载私有目录中版本统一的Jackson组件。 - 调整应用类加载优先级:如果无法修改Tomcat公共目录,在应用的
src/main/webapp/META-INF/context.xml中添加以下配置,强制当前应用优先加载自身私有依赖,覆盖Tomcat公共目录的旧版本组件:
<?xml version="1.0" encoding="UTF-8"?> <Context> <Loader delegate="false"/> </Context>
- 锁定项目依赖版本:在项目的pom.xml或build.gradle中显式指定所有Jackson组件的版本,确保和Log4j 2.13.3的要求完全匹配,避免项目内部出现依赖版本冲突。
内容的提问来源于stack exchange,提问作者Mykhaylo Adamovych
相关产品推荐
相关产品推荐

