Affects: Spring Framework 6.0.8
After updating Spring Framework from 6.0.7 to 6.0.8, class loading in our OSGi application appears to be broken. I have narrowed this down to being caused by the change for issue #30115.
Initially, the classLoader
passed to getProxy()
contains a BundleDelegatingClassLoader
:
BundleDelegatingClassLoader for [My Spring Bundle (a.b.c.symbolic.name;singleton:=true)]
The this.proxiedInterfaces
contains four interfaces, once of which is ours:
[interface a.b.c.MyInterface,
interface org.springframework.aop.SpringProxy,
interface org.springframework.aop.framework.Advised,
interface org.springframework.core.DecoratingProxy]
When the original classLoader
is used, we get a Proxy back for the implementing class. However, for the updated classLoader
EquinoxClassLoader
:
org.eclipse.osgi.internal.loader.EquinoxClassLoader@6af06218[org.springframework.spring-aop:6.0.8(id=427)]
We now get an error:
Stack Trace
java.lang.IllegalArgumentException: a.b.c.MyClass referenced from a method is not visible from class loader
at java.base/java.lang.reflect.Proxy$ProxyBuilder.ensureVisible(Proxy.java:883)
at java.base/java.lang.reflect.Proxy$ProxyBuilder.validateProxyInterfaces(Proxy.java:721)
at java.base/java.lang.reflect.Proxy$ProxyBuilder.<init>(Proxy.java:648)
at java.base/java.lang.reflect.Proxy.lambda$getProxyConstructor$1(Proxy.java:440)
at java.base/jdk.internal.loader.AbstractClassLoaderValue$Memoizer.get(AbstractClassLoaderValue.java:329)
at java.base/jdk.internal.loader.AbstractClassLoaderValue.computeIfAbsent(AbstractClassLoaderValue.java:205)
at java.base/java.lang.reflect.Proxy.getProxyConstructor(Proxy.java:438)
at java.base/java.lang.reflect.Proxy.newProxyInstance(Proxy.java:1037)
at org.springframework.aop.framework.JdkDynamicAopProxy.getProxy(JdkDynamicAopProxy.java:128)
at org.springframework.aop.framework.ProxyFactory.getProxy(ProxyFactory.java:110)
at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.buildProxy(AbstractAutoProxyCreator.java:517)
at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.createProxy(AbstractAutoProxyCreator.java:464)
at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.wrapIfNecessary(AbstractAutoProxyCreator.java:369)
at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessAfterInitialization(AbstractAutoProxyCreator.java:318)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:434)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1773)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:598)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:520)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:326)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:324)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:973)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:917)
at org.eclipse.gemini.blueprint.context.support.AbstractDelegatedExecutionApplicationContext.completeRefresh(AbstractDelegatedExecutionApplicationContext.java:323)
at org.eclipse.gemini.blueprint.extender.internal.dependencies.startup.DependencyWaiterApplicationContextExecutor$CompleteRefreshTask.run(DependencyWaiterApplicationContextExecutor.java:135)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
at java.base/java.lang.Thread.run(Thread.java:833)
Comment From: fantasy1713
This problem also occurs in version 5.3.27 upgrading from version 5.3.26. Our services are based on OSGI, gemini-blueprint and spring
The submission that causes this problem is https://github.com/spring-projects/spring-framework/commit/0c80e5f9e6afeca3447caac1449a45fa1fa03ea0.
Comment From: hnielsen-acn
This problem also occurs in version 5.3.27 upgrading from version 5.3.26. Our services are based on OSGI, gemini-blueprint and spring
The submission that causes this problem is 0c80e5f.
I can confirm this issue with spring-aop 5.3.27 in an OSGi gemini-blueprint environment.
Our stack trace is identical to the one posted by @chrislake in https://github.com/spring-projects/spring-framework/issues/30389#issue-1687792771.
Comment From: jhoeller
Sorry for not noticing this earlier... We'll fix that regression for the upcoming 6.0.10 and 5.3.28 releases, possibly through a more specific check for the JDK class proxying scenario in #30115.