Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Spring Boot DevTools on 5.1 fails with java.lang.LinkageError: loader attempted duplicate class definition [SPR-16902] #21441

Closed
spring-projects-issues opened this issue Jun 4, 2018 · 3 comments
Assignees
Labels
in: core Issues in core modules (aop, beans, core, context, expression) type: bug A general bug
Milestone

Comments

@spring-projects-issues
Copy link
Collaborator

spring-projects-issues commented Jun 4, 2018

Phil Webb opened SPR-16902 and commented

Spring Boot recently upgrade to Framework 5.1 SNAPSHOTS and we're now seeing "loader attempted duplicate class definition" errors with our devtools integration tests on Java 9 and Java 10 (Java 8 is fine).

Here's an example of a failing build.

Caused by: org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class org.springframework.boot.autoconfigure.http.HttpMessageConverters: Common causes of this problem include using a final class or a non-visible class; nested exception is org.springframework.cglib.core.CodeGenerationException: java.lang.LinkageError-->loader (instance of  jdk/internal/loader/ClassLoaders$AppClassLoader): attempted  duplicate class definition for name: "org/springframework/boot/autoconfigure/http/HttpMessageConverters$$EnhancerBySpringCGLIB$$1d90bff9"
	at org.springframework.aop.framework.CglibAopProxy.getProxy(CglibAopProxy.java:208) ~[spring-aop-5.1.0.BUILD-SNAPSHOT.jar:5.1.0.BUILD-SNAPSHOT]
	at org.springframework.aop.framework.ProxyFactory.getProxy(ProxyFactory.java:110) ~[spring-aop-5.1.0.BUILD-SNAPSHOT.jar:5.1.0.BUILD-SNAPSHOT]
	at org.springframework.context.annotation.ContextAnnotationAutowireCandidateResolver.buildLazyResolutionProxy(ContextAnnotationAutowireCandidateResolver.java:117) ~[spring-context-5.1.0.BUILD-SNAPSHOT.jar:5.1.0.BUILD-SNAPSHOT]
	at org.springframework.context.annotation.ContextAnnotationAutowireCandidateResolver.getLazyResolutionProxyIfNecessary(ContextAnnotationAutowireCandidateResolver.java:52) ~[spring-context-5.1.0.BUILD-SNAPSHOT.jar:5.1.0.BUILD-SNAPSHOT]
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1062) ~[spring-beans-5.1.0.BUILD-SNAPSHOT.jar:5.1.0.BUILD-SNAPSHOT]
	at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:818) ~[spring-beans-5.1.0.BUILD-SNAPSHOT.jar:5.1.0.BUILD-SNAPSHOT]
	at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:724) ~[spring-beans-5.1.0.BUILD-SNAPSHOT.jar:5.1.0.BUILD-SNAPSHOT]
	at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:197) ~[spring-beans-5.1.0.BUILD-SNAPSHOT.jar:5.1.0.BUILD-SNAPSHOT]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1276) ~[spring-beans-5.1.0.BUILD-SNAPSHOT.jar:5.1.0.BUILD-SNAPSHOT]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1133) ~[spring-beans-5.1.0.BUILD-SNAPSHOT.jar:5.1.0.BUILD-SNAPSHOT]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:543) ~[spring-beans-5.1.0.BUILD-SNAPSHOT.jar:5.1.0.BUILD-SNAPSHOT]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:503) ~[spring-beans-5.1.0.BUILD-SNAPSHOT.jar:5.1.0.BUILD-SNAPSHOT]
	... 34 common frames omitted
Caused by: org.springframework.cglib.core.CodeGenerationException: java.lang.LinkageError-->loader (instance of  jdk/internal/loader/ClassLoaders$AppClassLoader): attempted  duplicate class definition for name: "org/springframework/boot/autoconfigure/http/HttpMessageConverters$$EnhancerBySpringCGLIB$$1d90bff9"
	at org.springframework.cglib.core.ReflectUtils.defineClass(ReflectUtils.java:502) ~[spring-core-5.1.0.BUILD-SNAPSHOT.jar:5.1.0.BUILD-SNAPSHOT]
	at org.springframework.cglib.core.AbstractClassGenerator.generate(AbstractClassGenerator.java:359) ~[spring-core-5.1.0.BUILD-SNAPSHOT.jar:5.1.0.BUILD-SNAPSHOT]
	at org.springframework.cglib.proxy.Enhancer.generate(Enhancer.java:582) ~[spring-core-5.1.0.BUILD-SNAPSHOT.jar:5.1.0.BUILD-SNAPSHOT]
	at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:106) ~[spring-core-5.1.0.BUILD-SNAPSHOT.jar:5.1.0.BUILD-SNAPSHOT]
	at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:104) ~[spring-core-5.1.0.BUILD-SNAPSHOT.jar:5.1.0.BUILD-SNAPSHOT]
	at org.springframework.cglib.core.internal.LoadingCache$2.call(LoadingCache.java:54) ~[spring-core-5.1.0.BUILD-SNAPSHOT.jar:5.1.0.BUILD-SNAPSHOT]
	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) ~[na:na]
	at org.springframework.cglib.core.internal.LoadingCache.createEntry(LoadingCache.java:61) ~[spring-core-5.1.0.BUILD-SNAPSHOT.jar:5.1.0.BUILD-SNAPSHOT]
	at org.springframework.cglib.core.internal.LoadingCache.get(LoadingCache.java:34) ~[spring-core-5.1.0.BUILD-SNAPSHOT.jar:5.1.0.BUILD-SNAPSHOT]
	at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData.get(AbstractClassGenerator.java:130) ~[spring-core-5.1.0.BUILD-SNAPSHOT.jar:5.1.0.BUILD-SNAPSHOT]
	at org.springframework.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:315) ~[spring-core-5.1.0.BUILD-SNAPSHOT.jar:5.1.0.BUILD-SNAPSHOT]
	at org.springframework.cglib.proxy.Enhancer.createHelper(Enhancer.java:569) ~[spring-core-5.1.0.BUILD-SNAPSHOT.jar:5.1.0.BUILD-SNAPSHOT]
	at org.springframework.cglib.proxy.Enhancer.createClass(Enhancer.java:416) ~[spring-core-5.1.0.BUILD-SNAPSHOT.jar:5.1.0.BUILD-SNAPSHOT]
	at org.springframework.aop.framework.ObjenesisCglibAopProxy.createProxyClassAndInstance(ObjenesisCglibAopProxy.java:58) ~[spring-aop-5.1.0.BUILD-SNAPSHOT.jar:5.1.0.BUILD-SNAPSHOT]
	at org.springframework.aop.framework.CglibAopProxy.getProxy(CglibAopProxy.java:205) ~[spring-aop-5.1.0.BUILD-SNAPSHOT.jar:5.1.0.BUILD-SNAPSHOT]
	... 45 common frames omitted
Caused by: java.lang.LinkageError: loader (instance of  jdk/internal/loader/ClassLoaders$AppClassLoader): attempted  duplicate class definition for name: "org/springframework/boot/autoconfigure/http/HttpMessageConverters$$EnhancerBySpringCGLIB$$1d90bff9"
	at java.base/java.lang.ClassLoader.defineClass1(Native Method) ~[na:na]
	at java.base/java.lang.System$2.defineClass(System.java:2120) ~[na:na]
	at java.base/java.lang.invoke.MethodHandles$Lookup.defineClass(MethodHandles.java:964) ~[na:na]
	at java.base/jdk.internal.reflect.GeneratedMethodAccessor25.invoke(Unknown Source) ~[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:564) ~[na:na]
	at org.springframework.cglib.core.ReflectUtils.defineClass(ReflectUtils.java:498) ~[spring-core-5.1.0.BUILD-SNAPSHOT.jar:5.1.0.BUILD-SNAPSHOT]
	... 59 common frames omitted

The same tests on Spring Boot 2.0 (which uses Framework 5.0) pass fine on Java 8, 9 and 10.

My guess is this relates to #20414 and is probably caused by our slightly unusual DevTools classloader arrangement.


Affects: 5.1 RC1

Issue Links:

Referenced from: commits 6887802

@spring-projects-issues
Copy link
Collaborator Author

spring-projects-issues commented Jul 10, 2018

Juergen Hoeller commented

Since this is definitely a consequence of #20414 where we can't enforce the generation of a such a derived class into a specific ClassLoader, there is probably only one way out: keep using the old ClassLoader.defineClass approach for DevTools, even on JDK 9+. We already have a fallback for IllegalArgumentException coming out of the JDK 9 MethodHandles.Lookup API, so I guess we should simply fall back for LinkageError as well.

@spring-projects-issues
Copy link
Collaborator Author

Juergen Hoeller commented

We're falling back for IllegalArgumentException} (class in different package) as well as plain {{LinkageError (class already defined) now, matching the implementation of MethodHandles.Lookup.defineClass in JDK 9/10/11. We keep rethrowing all variants of LinkageError subclasses which typically indicate actual class definition issues.

This will be in the upcoming 5.1 snapshot. Please give it a try with DevTools and let me know how it goes...

@spring-projects-issues
Copy link
Collaborator Author

Andy Wilkinson commented

Thanks, Juergen. Boot 2.1's build is now passing on both Java 9 and Java 10.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: core Issues in core modules (aop, beans, core, context, expression) type: bug A general bug
Projects
None yet
Development

No branches or pull requests

2 participants