[使用由IntelliJ从PropertiesLoader加载的Spring Boot模块时,NoClassDefFoundError

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[使用由IntelliJ从PropertiesLoader加载的Spring Boot模块时,NoClassDefFoundError相关的知识,希望对你有一定的参考价值。

我有一个具有Spring Boot核心的应用程序,可以在运行时添加可选模块(使用PropertiesLoader)。

-Dloader.main=com.mycompany.App
-Dloader.path="C:\dir\some-module.jar"

这些模块被打包为胖子罐,因此它们具有所有依赖关系。我为此使用阴影插件。

其中一个附加模块依赖于JDBC,当我解压缩JAR时,可以看到存在Hikari的东西。

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

当我从JAR运行应用程序时,一切正常。但是,当我从IntellIJ的类路径运行时,Hikari类之一无法加载。

java.lang.IllegalStateException: Error processing condition on org.springframework.boot.autoconfigure.jdbc.DataSourceJmxConfiguration$Hikari
    at org.springframework.boot.autoconfigure.condition.SpringBootCondition.matches(SpringBootCondition.java:64) ~[spring-boot-autoconfigure-2.1.3.RELEASE.jar:2.1.3.RELEASE]
    at org.springframework.context.annotation.ConditionEvaluator.shouldSkip(ConditionEvaluator.java:108) ~[spring-context-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader$TrackedConditionEvaluator.shouldSkip(ConfigurationClassBeanDefinitionReader.java:447) ~[spring-context-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsForConfigurationClass(ConfigurationClassBeanDefinitionReader.java:128) ~[spring-context-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitions(ConfigurationClassBeanDefinitionReader.java:117) ~[spring-context-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:327) ~[spring-context-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:232) ~[spring-context-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:275) ~[spring-context-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:95) ~[spring-context-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:705) ~[spring-context-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:531) ~[spring-context-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:775) ~[spring-boot-2.1.3.RELEASE.jar:2.1.3.RELEASE]
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397) ~[spring-boot-2.1.3.RELEASE.jar:2.1.3.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:316) ~[spring-boot-2.1.3.RELEASE.jar:2.1.3.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1260) ~[spring-boot-2.1.3.RELEASE.jar:2.1.3.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1248) ~[spring-boot-2.1.3.RELEASE.jar:2.1.3.RELEASE]
    at com.mycompany.App.main(App.java:11) ~[classes/:na]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:567) ~[na:na]
    at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:48) ~[spring-boot-loader-2.1.3.RELEASE.jar:2.1.3.RELEASE]
    at org.springframework.boot.loader.Launcher.launch(Launcher.java:87) ~[spring-boot-loader-2.1.3.RELEASE.jar:2.1.3.RELEASE]
    at org.springframework.boot.loader.Launcher.launch(Launcher.java:50) ~[spring-boot-loader-2.1.3.RELEASE.jar:2.1.3.RELEASE]
    at org.springframework.boot.loader.PropertiesLauncher.main(PropertiesLauncher.java:593) ~[spring-boot-loader-2.1.3.RELEASE.jar:2.1.3.RELEASE]
Caused by: java.lang.IllegalStateException: Failed to introspect Class [org.springframework.boot.autoconfigure.jdbc.DataSourceConfiguration$Hikari] from ClassLoader [jdk.internal.loader.ClassLoaders$AppClassLoader@2626b418]
    at org.springframework.util.ReflectionUtils.getDeclaredMethods(ReflectionUtils.java:686) ~[spring-core-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    at org.springframework.util.ReflectionUtils.doWithMethods(ReflectionUtils.java:583) ~[spring-core-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    at org.springframework.util.ReflectionUtils.doWithMethods(ReflectionUtils.java:568) ~[spring-core-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    at org.springframework.util.ReflectionUtils.getUniqueDeclaredMethods(ReflectionUtils.java:626) ~[spring-core-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    at java.base/java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1705) ~[na:na]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.getTypeForFactoryMethod(AbstractAutowireCapableBeanFactory.java:738) ~[spring-beans-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.determineTargetType(AbstractAutowireCapableBeanFactory.java:679) ~[spring-beans-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.predictBeanType(AbstractAutowireCapableBeanFactory.java:647) ~[spring-beans-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.isFactoryBean(AbstractBeanFactory.java:1518) ~[spring-beans-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.isFactoryBean(AbstractBeanFactory.java:1023) ~[spring-beans-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    at org.springframework.boot.autoconfigure.condition.BeanTypeRegistry.addBeanTypeForNonAliasDefinition(BeanTypeRegistry.java:195) ~[spring-boot-autoconfigure-2.1.3.RELEASE.jar:2.1.3.RELEASE]
    at org.springframework.boot.autoconfigure.condition.BeanTypeRegistry.addBeanTypeForNonAliasDefinition(BeanTypeRegistry.java:159) ~[spring-boot-autoconfigure-2.1.3.RELEASE.jar:2.1.3.RELEASE]
    at org.springframework.boot.autoconfigure.condition.BeanTypeRegistry.addBeanType(BeanTypeRegistry.java:152) ~[spring-boot-autoconfigure-2.1.3.RELEASE.jar:2.1.3.RELEASE]
    at org.springframework.boot.autoconfigure.condition.BeanTypeRegistry.updateTypesIfNecessary(BeanTypeRegistry.java:140) ~[spring-boot-autoconfigure-2.1.3.RELEASE.jar:2.1.3.RELEASE]
    at java.base/java.util.Iterator.forEachRemaining(Iterator.java:133) ~[na:na]
    at org.springframework.boot.autoconfigure.condition.BeanTypeRegistry.updateTypesIfNecessary(BeanTypeRegistry.java:135) ~[spring-boot-autoconfigure-2.1.3.RELEASE.jar:2.1.3.RELEASE]
    at org.springframework.boot.autoconfigure.condition.BeanTypeRegistry.getNamesForType(BeanTypeRegistry.java:97) ~[spring-boot-autoconfigure-2.1.3.RELEASE.jar:2.1.3.RELEASE]
    at org.springframework.boot.autoconfigure.condition.OnBeanCondition.collectBeanNamesForType(OnBeanCondition.java:298) ~[spring-boot-autoconfigure-2.1.3.RELEASE.jar:2.1.3.RELEASE]
    at org.springframework.boot.autoconfigure.condition.OnBeanCondition.getBeanNamesForType(OnBeanCondition.java:289) ~[spring-boot-autoconfigure-2.1.3.RELEASE.jar:2.1.3.RELEASE]
    at org.springframework.boot.autoconfigure.condition.OnBeanCondition.getBeanNamesForType(OnBeanCondition.java:278) ~[spring-boot-autoconfigure-2.1.3.RELEASE.jar:2.1.3.RELEASE]
    at org.springframework.boot.autoconfigure.condition.OnBeanCondition.getMatchingBeans(OnBeanCondition.java:189) ~[spring-boot-autoconfigure-2.1.3.RELEASE.jar:2.1.3.RELEASE]
    at org.springframework.boot.autoconfigure.condition.OnBeanCondition.getMatchOutcome(OnBeanCondition.java:138) ~[spring-boot-autoconfigure-2.1.3.RELEASE.jar:2.1.3.RELEASE]
    at org.springframework.boot.autoconfigure.condition.SpringBootCondition.matches(SpringBootCondition.java:47) ~[spring-boot-autoconfigure-2.1.3.RELEASE.jar:2.1.3.RELEASE]
    ... 24 common frames omitted
Caused by: java.lang.NoClassDefFoundError: com/zaxxer/hikari/HikariDataSource
    at java.base/java.lang.Class.getDeclaredMethods0(Native Method) ~[na:na]
    at java.base/java.lang.Class.privateGetDeclaredMethods(Class.java:3171) ~[na:na]
    at java.base/java.lang.Class.getDeclaredMethods(Class.java:2314) ~[na:na]
    at org.springframework.util.ReflectionUtils.getDeclaredMethods(ReflectionUtils.java:668) ~[spring-core-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    ... 46 common frames omitted
Caused by: java.lang.ClassNotFoundException: com.zaxxer.hikari.HikariDataSource
    at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:583) ~[na:na]
    at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178) ~[na:na]
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521) ~[na:na]
    ... 50 common frames omitted

当我在org.springframework.boot.loader.Launcher中的此处放置断点时>

protected void launch(String[] args) throws Exception 
    JarFile.registerUrlProtocolHandler();
    ClassLoader classLoader = this.createClassLoader(this.getClassPathArchives());
    this.launch(args, this.getMainClass(), classLoader); //breakpoint 

[我可以看到LaunchedURLClassLoader是正确创建的(即它具有对模块JAR的引用),并且在我评估时

classLoader.loadClass("com.zaxxer.hikari.HikariDataSource")

在调试器中,我可以看到可以从此处很好地加载该类。

但是,当DataSourceJmxConfiguration$Hikari被加载时,由于Spring Boot Auto-Configure捆绑在核心Spring Boot应用程序中,因此它会与父类加载器一起加载。当Spring尝试调用getDeclaredMethods时,由于HikariDataSource需要由子类加载器加载,并且父级不知道它的任何子级,因此它会崩溃。

[HikariDataSource当然在类路径上,因为DataSourceJmxConfiguration$Hikari是有条件的]

@Configuration
@ConditionalOnClass(HikariDataSource.class)
@ConditionalOnSingleCandidate(DataSource.class)
static class Hikari 
    //...

我无法确定直接从JAR运行与运行有什么不同,以及为什么它可以在IntelliJ的运行中起作用。我可以看到初始的类加载器是用相同的方式创建的。

不幸的是,这个问题并不适合在此处发布可复制的示例(我可以

,但您必须自己构建整个项目结构)。相反,我创建了a MCVE on GitHub-它只有5个文件,其中3个是POM。

关于这些类的加载方式有什么区别,我该如何解决?

我可以继续作为“ JAR应用程序”运行,但可以,但是作为“应用程序”运行更方便,因为这样我就可以进行热替换,而无需为每个应用程序都构建一个新的JAR。更改。我也想知道我的理解。

我有一个具有Spring Boot核心的应用程序,可以在运行时添加可选模块(使用PropertiesLoader)。 -Dloader.main = com.mycompany.App -Dloader.path =“ C:\ dir \ some-module.jar” ...

答案

我已经检查了Intellij正在运行的Java命令(它写在运行窗口的第一行中,您可以复制并检查它),当您将其作为应用程序运行时,Intellij会以编程方式在-j中添加-classpath选项。 java命令。并且在类路径中,jdbc-1.0-SNAPSHOT.jar不存在(似乎没有包含所需类的任何jar)。所以我将此配置添加到您的配置中(“测试(失败)”一项)

另一答案

您之前如何制作罐子?

以上是关于[使用由IntelliJ从PropertiesLoader加载的Spring Boot模块时,NoClassDefFoundError的主要内容,如果未能解决你的问题,请参考以下文章

从 IntelliJ Idea 运行/调试 Spring Boot 应用程序

在IntelliJ中调试Ant项目时,行号信息不可用错误

IntelliJ IDEA方法参数无法正确显示

推荐一款 IntelliJ IDEA 神级插件,由 ChatGPT 团队开发,免费使用,堪称辅助神器!

由 AspectJ 编译器编织的 Spring 方面在 Maven 中工作,但在 IntelliJ IDEA 中没有

Intellij IDEA 创建消息驱动Bean - 接收JMS消息