My company backend app's war size was about 100 MB, so we decided to change scope of all maven dependencies to provided. Jars were moved from .war to opt/tomcat/shared/lib folder (according to this instruction https://www.mulesoft.com/tcat/tomcat-classpath). Everything worked great, we deployed 2 backend apps on this server using this configuration. After we added third similar backend app, we can't use log in oauth2 service because in logs we can see the following error:
org.springframework.cglib.core.CodeGenerationException: java.lang.LinkageError-->loader java.net.URLClassLoader @2f943d71 (instance of java.net.URLClassLoader, child of java.net.URLClassLoader @bd8db5a java.net.URLClassLoader) attempted duplicate class definition for org.springframework.security.oauth2.provider.token.DefaultTokenServices$$FastClassBySpringCGLIB$$5a1f25c.
Previous two apps still works ok, but the third not. Before every deployment we clear tomcat's work folder. We use Java 11 SpringBoot2, OpenJDK 11, Tomcat 9.0.21. Class DefaultTokenServices is in spring-security-oauth2-2.3.5.RELEASE.jar, which we placed in opt/tomcat/shared/lib folder along with other jars.
I think that Tomcat's SharedClassLoader (which is used to load jars from Tomcat's tomcat/shared/lib folder) isn't thread-safe because this LinkageError seems to occur when 2 or more threads try to define the same class in parallel.
The solution is to add AllowParallelDefineClass flag to JVM (tomcat/bin/catalina.sh). It causes that when 2 or more threads try to define the same class in parallel, instead of throwing an error both of them will be returned the result of the first requester.
-XX:+AllowParallelDefineClass