Spring Boot Maven插件与antlr4-runtime依赖冲突致初始化报错
解决Spring Boot初始化时antlr4-runtime版本冲突引发的NoClassDefFoundError
问题现象
运行Spring Boot应用初始化阶段抛出以下异常:
Caused by: java.lang.NoClassDefFoundError: org/antlr/v4/runtime/misc/ParseCancellationException at org.hibernate.query.internal.QueryEngineImpl.resolveHqlTranslator(QueryEngineImpl.java:155) ~[hibernate-core-6.4.4.Final.jar:6.4.4.Final] at org.hibernate.query.internal.QueryEngineImpl.from(QueryEngineImpl.java:63) ~[hibernate-core-6.4.4.Final.jar:6.4.4.Final] at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:285) ~[hibernate-core-6.4.4.Final.jar:6.4.4.Final] at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:450) ~[hibernate-core-6.4.4.Final.jar:6.4.4.Final] at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1507) ~[hibernate-core-6.4.4.Final.jar:6.4.4.Final] at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:75) ~[spring-orm-6.1.4.jar:6.1.4] at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:388) ~[spring-orm-6.1.4.jar:6.1.4] at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:409) ~[spring-orm-6.1.4.jar:6.1.4] at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:396) ~[spring-orm-6.1.4.jar:6.1.4] at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:364) ~[spring-orm-6.1.4.jar:6.1.4] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1833) ~[spring-beans-6.1.4.jar:6.1.4] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1782) ~[spring-beans-6.1.4.jar:6.1.4] ... 21 more Caused by: java.lang.ClassNotFoundException: org.antlr.v4.runtime.misc.ParseCancellationException at jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641) ~[?:?] at jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188) ~[?:?] at java.lang.ClassLoader.loadClass(ClassLoader.java:520) ~[?:?] at org.hibernate.query.internal.QueryEngineImpl.resolveHqlTranslator(QueryEngineImpl.java:155) ~[hibernate-core-6.4.4.Final.jar:6.4.4.Final] at org.hibernate.query.internal.QueryEngineImpl.from(QueryEngineImpl.java:63) ~[hibernate-core-6.4.4.Final.jar:6.4.4.Final] at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:285) ~[hibernate-core-6.4.4.Final.jar:6.4.4.Final]
问题原因
排查发现spring-boot-maven-plugin通过传递依赖引入的antlr4-runtime-4.7.2,覆盖了spring-data提供的antlr4-runtime-4.13.0版本。低版本中缺少ParseCancellationException类,导致应用初始化失败。
尝试在插件的<excludes>配置中排除该依赖,但未生效,原有配置如下:
<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <executions> <execution> <goals> <goal>repackage</goal> </goals> </execution> </executions> <configuration> <excludes> <exclude> <groupId>org.antlr</groupId> <artifactId>antlr4-runtime</artifactId> </exclude> </excludes> <classifier>exec</classifier> </configuration> </plugin> </plugins> </build> <profile> <id>IT</id> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <executions> <execution> <goals> <goal>repackage</goal> </goals> </execution> </executions> <configuration> <excludes> <exclude> <groupId>org.antlr</groupId> <artifactId>antlr4-runtime</artifactId> </exclude> </excludes> <classifier>exec</classifier> </configuration> </plugin> </plugins> </build> </profile>
解决方案
方案1:显式声明高版本antlr4-runtime依赖
利用Maven的依赖仲裁机制,在项目<dependencies>中直接声明需要的高版本antlr4-runtime,强制Maven使用该版本:
<dependency> <groupId>org.antlr</groupId> <artifactId>antlr4-runtime</artifactId> <version>4.13.0</version> </dependency>
方案2:正确排除插件的传递依赖
原配置中的<excludes>用于打包阶段排除jar包,而非排除插件自身的传递依赖。需要在插件的<dependencies>中排除spring-boot-loader-tools带来的antlr4-runtime:
<plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <executions> <execution> <goals> <goal>repackage</goal> </goals> </execution> </executions> <configuration> <classifier>exec</classifier> </configuration> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-loader-tools</artifactId> <version>${spring-boot.version}</version> <exclusions> <exclude> <groupId>org.antlr</groupId> <artifactId>antlr4-runtime</artifactId> </exclude> </exclusions> </dependency> </dependencies> </plugin>
如果有多环境profile(如示例中的IT环境),需要在对应profile的插件配置中做相同的依赖排除操作。
内容的提问来源于stack exchange,提问作者Abirami
相关产品推荐
相关产品推荐

