Description
Rob Winch opened SPR-10261 and commented
Despite having consistent Spring versions and ensuring I have spring-core-3.2.1.RELEASE.jar on the classpath, when loading Java Configuration, I occassionally get the following Error:
java.lang.NoClassDefFoundError: org.springframework.beans.FatalBeanException
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:581)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1029)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:925)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:490)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:461)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:295)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:292)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:626)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:932)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:479)
at org.springframework.context.annotation.AnnotationConfigApplicationContext.<init>(AnnotationConfigApplicationContext.java:73)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:525)
at org.codehaus.groovy.reflection.CachedConstructor.invoke(CachedConstructor.java:77)
at org.codehaus.groovy.reflection.CachedConstructor.doConstructorInvoke(CachedConstructor.java:71)
at org.codehaus.groovy.runtime.callsite.ConstructorSite.callConstructor(ConstructorSite.java:42)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallConstructor(CallSiteArray.java:54)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:182)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:190)
at groovy.groovy.GroovyReturnsSubclassTests.returnsSubclass(GroovyReturnsSubclassTests.groovy:16)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:76)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
This seems to be associated with a StackOverFlowException where the stack looks something like the following:
ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(Object, Method, Object[], MethodProxy) line: 297
GroovyReturnsSubclassTests$MyConfig$$EnhancerByCGLIB$$3aca3be8.builder() line: not available
GroovyReturnsSubclassTests$MyConfig$$EnhancerByCGLIB$$3aca3be8(GroovyReturnsSubclassTests$MyConfig).builder() line: not available
GroovyReturnsSubclassTests$MyConfig$$EnhancerByCGLIB$$3aca3be8.CGLIB$builder$6() line: not available
GroovyReturnsSubclassTests$MyConfig$$EnhancerByCGLIB$$3aca3be8$$FastClassByCGLIB$$2a4c4776.invoke(int, Object, Object[]) line: not available
MethodProxy.invokeSuper(Object, Object[]) line: 228
ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(Object, Method, Object[], MethodProxy) line: 285
GroovyReturnsSubclassTests$MyConfig$$EnhancerByCGLIB$$3aca3be8.builder() line: not available
NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]
NativeMethodAccessorImpl.invoke(Object, Object[]) line: 57
DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 43
Method.invoke(Object, Object...) line: 601
CglibSubclassingInstantiationStrategy(SimpleInstantiationStrategy).instantiate(RootBeanDefinition, String, BeanFactory, Object, Method, Object[]) line: 160
ConstructorResolver.instantiateUsingFactoryMethod(String, RootBeanDefinition, Object[]) line: 570
DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).instantiateUsingFactoryMethod(String, RootBeanDefinition, Object[]) line: 1029
DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).createBeanInstance(String, RootBeanDefinition, Object[]) line: 925
DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).doCreateBean(String, RootBeanDefinition, Object[]) line: 490
DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).createBean(String, RootBeanDefinition, Object[]) line: 461
AbstractBeanFactory$1.getObject() line: 295
DefaultListableBeanFactory(DefaultSingletonBeanRegistry).getSingleton(String, ObjectFactory) line: 223
DefaultListableBeanFactory(AbstractBeanFactory).doGetBean(String, Class<T>, Object[], boolean) line: 292
DefaultListableBeanFactory(AbstractBeanFactory).getBean(String) line: 194
ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(Object, Method, Object[], MethodProxy) line: 297
GroovyReturnsSubclassTests$MyConfig$$EnhancerByCGLIB$$3aca3be8.builder() line: not available
GroovyReturnsSubclassTests$MyConfig$$EnhancerByCGLIB$$3aca3be8(GroovyReturnsSubclassTests$MyConfig).builder() line: not available
GroovyReturnsSubclassTests$MyConfig$$EnhancerByCGLIB$$3aca3be8.CGLIB$builder$6() line: not available
GroovyReturnsSubclassTests$MyConfig$$EnhancerByCGLIB$$3aca3be8$$FastClassByCGLIB$$2a4c4776.invoke(int, Object, Object[]) line: not available
MethodProxy.invokeSuper(Object, Object[]) line: 228
ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(Object, Method, Object[], MethodProxy) line: 285
GroovyReturnsSubclassTests$MyConfig$$EnhancerByCGLIB$$3aca3be8.builder() line: not available
NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]
NativeMethodAccessorImpl.invoke(Object, Object[]) line: 57
DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 43
Method.invoke(Object, Object...) line: 601
CglibSubclassingInstantiationStrategy(SimpleInstantiationStrategy).instantiate(RootBeanDefinition, String, BeanFactory, Object, Method, Object[]) line: 160
ConstructorResolver.instantiateUsingFactoryMethod(String, RootBeanDefinition, Object[]) line: 570
DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).instantiateUsingFactoryMethod(String, RootBeanDefinition, Object[]) line: 1029
DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).createBeanInstance(String, RootBeanDefinition, Object[]) line: 925
DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).doCreateBean(String, RootBeanDefinition, Object[]) line: 490
DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).createBean(String, RootBeanDefinition, Object[]) line: 461
AbstractBeanFactory$1.getObject() line: 295
DefaultListableBeanFactory(DefaultSingletonBeanRegistry).getSingleton(String, ObjectFactory) line: 223
DefaultListableBeanFactory(AbstractBeanFactory).doGetBean(String, Class<T>, Object[], boolean) line: 292
DefaultListableBeanFactory(AbstractBeanFactory).getBean(String) line: 194
DefaultListableBeanFactory.preInstantiateSingletons() line: 626
AnnotationConfigApplicationContext(AbstractApplicationContext).finishBeanFactoryInitialization(ConfigurableListableBeanFactory) line: 932
AnnotationConfigApplicationContext(AbstractApplicationContext).refresh() line: 479
AnnotationConfigApplicationContext.<init>(Class<?>...) line: 73
NativeConstructorAccessorImpl.newInstance0(Constructor, Object[]) line: not available [native method]
NativeConstructorAccessorImpl.newInstance(Object[]) line: 57
DelegatingConstructorAccessorImpl.newInstance(Object[]) line: 45
Constructor<T>.newInstance(Object...) line: 525
CachedConstructor.invoke(Object[]) line: 77
CachedConstructor.doConstructorInvoke(Object[]) line: 71
ConstructorSite.callConstructor(Object, Object[]) line: 42
CallSiteArray.defaultCallConstructor(CallSite, Object, Object[]) line: 54
AbstractCallSite.callConstructor(Object, Object[]) line: 182
AbstractCallSite.callConstructor(Object, Object) line: 190
GroovyReturnsSubclassTests.returnsSubclass() line: 16
NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]
NativeMethodAccessorImpl.invoke(Object, Object[]) line: 57
DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 43
Method.invoke(Object, Object...) line: 601
FrameworkMethod$1.runReflectiveCall() line: 44
FrameworkMethod$1(ReflectiveCallable).run() line: 15
FrameworkMethod.invokeExplosively(Object, Object...) line: 41
InvokeMethod.evaluate() line: 20
BlockJUnit4ClassRunner.runChild(FrameworkMethod, RunNotifier) line: 76
BlockJUnit4ClassRunner.runChild(Object, RunNotifier) line: 50
ParentRunner$3.run() line: 193
ParentRunner$1.schedule(Runnable) line: 52
BlockJUnit4ClassRunner(ParentRunner<T>).runChildren(RunNotifier) line: 191
ParentRunner<T>.access$000(ParentRunner, RunNotifier) line: 42
ParentRunner$2.evaluate() line: 184
BlockJUnit4ClassRunner(ParentRunner<T>).run(RunNotifier) line: 236
JUnit4TestClassReference(JUnit4TestReference).run(TestExecution) line: 50
TestExecution.run(ITestReference[]) line: 38
RemoteTestRunner.runTests(String[], String, TestExecution) line: 467
RemoteTestRunner.runTests(TestExecution) line: 683
RemoteTestRunner.run() line: 390
RemoteTestRunner.main(String[]) line: 197
Notice that the following two lines are invoked repeatedly:
...
ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(Object, Method, Object[], MethodProxy) line: 297
...
BeanMethodInterceptor.intercept(Object, Method, Object[], MethodProxy) line: 285
...
ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(Object, Method, Object[], MethodProxy) line: 297
...
BeanMethodInterceptor.intercept(Object, Method, Object[], MethodProxy) line: 285
This seems to occur when ConfigurationClassEnhancer$BeanMethodInterceptor.intercept has a value referring to the superclass for cglibMethodProxy instead of the current class value. For example the following Groovy code:
public class GroovyReturnsSubclassTests {
private AnnotationConfigApplicationContext context;
@Test
public void returnsSubclass() {
context = new AnnotationConfigApplicationContext(MyConfig.class);
}
@Configuration
static class MyConfig extends BaseConfig {
@Bean
public String builder() throws Exception {
return null;
}
}
@Configuration
static abstract class BaseConfig {
public abstract Object builder() throws Exception;
}
}
Will randomly produce the following values for cglibMethodProxy:
cglibMethodProxy MethodProxy (id=57)
createInfo MethodProxy$CreateInfo (id=88)
fastClassInfo null
initLock Object (id=97)
sig1 Signature (id=102)
desc "()Ljava/lang/Object;" (id=115)
name "builder" (id=74)
sig2 Signature (id=106)
desc "()Ljava/lang/Object;" (id=115)
name "CGLIB$builder$0" (id=137)
This causes an infinite recursion, but the following value for cglibMethodProxy works:
cglibMethodProxy MethodProxy (id=57)
createInfo MethodProxy$CreateInfo (id=88)
fastClassInfo null
initLock Object (id=96)
sig1 Signature (id=101)
desc "()Ljava/lang/String;" (id=114)
name "builder" (id=73)
sig2 Signature (id=103)
desc "()Ljava/lang/String;" (id=114)
name "CGLIB$builder$6" (id=135)
Additional Notes:
- It appears to only occur with Groovy. It does not seem to happen with Java
- If builder() defines the same return type for the sublcass and parent it seems to work
- Sometimes it works just fine sometimes it fails with the NoClassDefFoundError: FatalBeanException
- A configuration like this might be usefult to do something like this:
@Configuration
static class MyConfig extends BaseConfig {
@Bean
public String builder() throws Exception {
return null;
}
}
@Configuration
static abstract class BaseConfig {
@Bean
public UsesBuilder usesBuilder() {
Object b = builder();
return new UsesBuilder(b);
}
public abstract Object builder() throws Exception;
}
- I will post a complete project that demonstrates the issue in the comments
Affects: 3.2.1
Issue Links:
- Configuration class implementing Provider interface throws StackOverflowError after upgrading to Java 7 [SPR-11830] #16449 Configuration class implementing Provider interface throws StackOverflowError after upgrading to Java 7
Referenced from: commits spring-attic/spring-framework-issues@bd98e51, spring-attic/spring-framework-issues@a0e257c