I try to use 'UrlClassLoader' to load a jar package. In this jar package, an 'AnnotationConfigApplicationContext' will be started, and the '@ImportAutoConfiguration' annotation will be used. At this time, my application will throw an 'IllegalargumentException' caused by 'ClassNotFoundException'.
I have a simple example. (https://github.com/aoyvx/CustomClassLoaderExample). The following stack will be thrown when the module'app-one 'is run.
Exception in thread "main" java.lang.IllegalArgumentException: Could not find class [org.example.impl.SimpleConfig]
at org.springframework.util.ClassUtils.resolveClassName(ClassUtils.java:334)
at org.springframework.boot.autoconfigure.ImportAutoConfigurationImportSelector.getAnnotations(ImportAutoConfigurationImportSelector.java:132)
at org.springframework.boot.autoconfigure.ImportAutoConfigurationImportSelector.getCandidateConfigurations(ImportAutoConfigurationImportSelector.java:77)
at org.springframework.boot.autoconfigure.AutoConfigurationImportSelector.getAutoConfigurationEntry(AutoConfigurationImportSelector.java:125)
at org.springframework.boot.autoconfigure.AutoConfigurationImportSelector$AutoConfigurationGroup.process(AutoConfigurationImportSelector.java:440)
at org.springframework.context.annotation.ConfigurationClassParser$DeferredImportSelectorGrouping.getImports(ConfigurationClassParser.java:879)
at org.springframework.context.annotation.ConfigurationClassParser$DeferredImportSelectorGroupingHandler.processGroupImports(ConfigurationClassParser.java:809)
at org.springframework.context.annotation.ConfigurationClassParser$DeferredImportSelectorHandler.process(ConfigurationClassParser.java:780)
at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:193)
at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:331)
at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:247)
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:311)
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:112)
at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:746)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:564)
at org.example.impl.EchoApp.init(EchoApp.java:15)
at com.example.app.App.main(App.java:15)
Caused by: java.lang.ClassNotFoundException: org.example.impl.SimpleConfig
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520)
at java.base/java.lang.Class.forName0(Native Method)
at java.base/java.lang.Class.forName(Class.java:467)
at org.springframework.util.ClassUtils.forName(ClassUtils.java:284)
at org.springframework.util.ClassUtils.resolveClassName(ClassUtils.java:324)
... 16 more
Disconnected from the target VM, address: '127.0.0.1:54192', transport: 'socket'
Process finished with exit code 1
I modified ImportAutoConfigurationImportSelector#getExclusions and ImportAutoConfigurationImportSelector#getAnnotations in module app-b, replace null with getBeanClassLoader(). at this time, the program can run normally.
Comment From: aoyvx
I want to know why ImportAutoConfigurationImportSelector selects null or default ClassLoader to load classes.
If I replace it with beanClassLoader, will there be any side effects.
Comment From: philwebb
I think this might be an oversight on our part. I seem to remember we've had a few issues in this area in the past but I can't find them in the issue tracker. It feels like using the bean classloader is the right thing to do with those calls. Flagging for team attention so see if anyone disagrees.
Comment From: aoyvx
@philwebb If I can, I hope I can submit this PR, because this will be my first PR to springboot.🤭
Comment From: wilkinsona
I seem to remember we've had a few issues in this area in the past but I can't find them in the issue tracker
I have a recollection of doing a sweep of the codebase trying to consistently use the bean class loader or the class loader from the resource loader or something like that. I can't find the issue either though 🤷.
It feels like using the bean classloader is the right thing to do with those calls
+1, particularly as we already use the bean class loader to load the factory names. We should consistently use the same class loader.
I hope I can submit this PR
Yes please, @aoyvx. A PR would be most welcome.
Comment From: snicoll
Closing in favor of PR #31798