We are in the process of making our application run on Java 17 using Spring Boot 2.6 and Spring Framework 5.3.
We have a test setup where we register our web endpoints in different servlets. We do this by using the ServletRegistrationBean
from Spring Boot and create a DispatcherServlet
using an AnnotationConfigWebApplicationContext
.
A linkage error occurs when we try to have different tests with different configuration, i.e. each test will create its own application context.
I have created a small project showcasing this problem (https://github.com/filiphr/spring-java-17-duplicate-class-definition).
The main error is
Caused by: java.lang.LinkageError: loader 'app' attempted duplicate class definition for com.example.rest.DemoService$$EnhancerBySpringCGLIB$$8972e13d. (com.example.rest.DemoService$$EnhancerBySpringCGLIB$$8972e13d is in unnamed module of loader 'app')
at java.base/java.lang.ClassLoader.defineClass0(Native Method) ~[na:na]
at java.base/java.lang.System$2.defineClass(System.java:2307) ~[na:na]
at java.base/java.lang.invoke.MethodHandles$Lookup$ClassDefiner.defineClass(MethodHandles.java:2439) ~[na:na]
at java.base/java.lang.invoke.MethodHandles$Lookup$ClassDefiner.defineClass(MethodHandles.java:2416) ~[na:na]
at java.base/java.lang.invoke.MethodHandles$Lookup.defineClass(MethodHandles.java:1843) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[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:568) ~[na:na]
at org.springframework.cglib.core.ReflectUtils.defineClass(ReflectUtils.java:577) ~[spring-core-5.3.15.jar:5.3.15]
... 135 common frames omitted
I have also found #25940 which looks like it has the same cause for the problem. However, I believe that my example is slightly less complicated.
Is it possible for Spring to do something and not create duplicate class definitions and create unique class names per application context as commented by @iherasymenko in https://github.com/spring-projects/spring-framework/issues/25940#issuecomment-712658780?
Comment From: sbrannen
Indeed, this effectively a duplicate of #25940.
I have created a small project showcasing this problem (https://github.com/filiphr/spring-java-17-duplicate-class-definition).
I don't see any code in that repo. There's only a README file.
Comment From: filiphr
I don't see any code in that repo. There's only a README file.
Really silly of me, I forgot to also push the classes 🤦. I have pushed the changes there now as well. Let me know what you think and whether this is something that can be addresses in Spring 5, the other issue is targeted towards Spring 6.
Indeed, this effectively a duplicate of #25940.
That's why I expected, but wanted to make sure.
Comment From: sbrannen
Related issues:
-
25940
-
27622
Comment From: sbrannen
Hi @filiphr,
Thanks for adding the code to your repo.
We will take that into account when investigating this issue, which we plan to do in conjunction with #25940.
Let me know what you think and whether this is something that can be addresses in Spring 5, the other issue is targeted towards Spring 6.
We do not currently have any plans to address this in 5.3.x, but we will reassess that if we do something for 6.0.x.
I am therefore closing this as a duplicate of #25940.
Comment From: filiphr
We do not currently have any plans to address this in 5.3.x, but we will reassess that if we do something for 6.0.x.
Thanks for letting me know @sbrannen. I am going to look for an alternative way to solve the problem that we are facing.
Comment From: mxhc
@filiphr what was the approach you took to solve this problem?
Comment From: filiphr
@mxhc we are not using CGLIB proxies. This means that we created interfaces and then classes implementing those interface. If it is done like that they it works