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.