IndyBootstrap classloading problem
See original GitHub issueAs reported in forum. Problem with 1.18.1(and current master branch) versions. Application on spring boot version 2.3.4, tomcat version - 9.0.37-jdk11-openjdk.
2020-10-21 14:48:58,919 [main] TRACE co.elastic.apm.agent.bci.ElasticApmAgent - Advice co.elastic.apm.agent.bootdelegation.BootstrapDelegationClassLoaderInstrumentation is loaded by null
2020-10-21 14:48:58,920 [main] TRACE co.elastic.apm.agent.bci.ElasticApmAgent - java.net.URLClassLoader@72cf2de5 can load advice (co.elastic.apm.agent.bootdelegation.BootstrapDelegationClassLoaderInstrumentation): true
2020-10-21 14:48:58,920 [main] TRACE co.elastic.apm.agent.bci.ElasticApmAgent - Advice co.elastic.apm.agent.bootdelegation.BootstrapDelegationClassLoaderInstrumentation is loaded by null
2020-10-21 14:48:58,920 [main] TRACE co.elastic.apm.agent.bci.ElasticApmAgent - jdk.internal.loader.ClassLoaders$AppClassLoader@3d4eac69 can load advice (co.elastic.apm.agent.bootdelegation.BootstrapDelegationClassLoaderInstrumentation): true
2020-10-21 14:48:58,920 [main] TRACE co.elastic.apm.agent.bci.ElasticApmAgent - Advice co.elastic.apm.agent.bootdelegation.BootstrapDelegationClassLoaderInstrumentation is loaded by null
2020-10-21 14:48:58,920 [main] TRACE co.elastic.apm.agent.bci.ElasticApmAgent - jdk.internal.loader.ClassLoaders$PlatformClassLoader@16612a51 can load advice (co.elastic.apm.agent.bootdelegation.BootstrapDelegationClassLoaderInstrumentation): true
2020-10-21 14:48:58,920 [main] TRACE co.elastic.apm.agent.bci.ElasticApmAgent - Advice co.elastic.apm.agent.bootdelegation.BootstrapDelegationClassLoaderInstrumentation is loaded by null
2020-10-21 14:48:58,920 [main] TRACE co.elastic.apm.agent.bci.ElasticApmAgent - bootstrap classloader
2020-10-21 14:48:59,227 [main] DEBUG co.elastic.apm.agent.bci.IndyPluginClassLoaderFactory - Creating plugin class loader for ParallelWebappClassLoader
context: demo1
delegate: false
----------> Parent Classloader:
java.net.URLClassLoader@72cf2de5
containing [co.elastic.apm.agent.springwebmvc.ExceptionHandlerInstrumentation, co.elastic.apm.agent.springwebmvc.package-info, co.elastic.apm.agent.springwebmvc.ExceptionHandlerInstrumentation$ExceptionHandlerAdviceService, co.elastic.apm.agent.springwebmvc.ViewRenderInstrumentation$ViewRenderAdviceService, co.elastic.apm.agent.springwebmvc.SpringTransactionNameInstrumentation, co.elastic.apm.agent.springwebmvc.SpringTransactionNameInstrumentation$HandlerAdapterAdvice, co.elastic.apm.agent.springwebmvc.SpringServiceNameInstrumentation$SpringServiceNameAdvice, co.elastic.apm.agent.springwebmvc.SpringServiceNameInstrumentation, co.elastic.apm.agent.springwebmvc.ViewRenderInstrumentation]
2020-10-21 14:48:59,236 [main] ERROR co.elastic.apm.agent.bci.IndyBootstrap - no such method: co.elastic.apm.agent.springwebmvc.SpringServiceNameInstrumentation$SpringServiceNameAdvice.afterInitPropertySources(WebApplicationContext)void/invokeStatic
java.lang.IllegalAccessException: no such method: co.elastic.apm.agent.springwebmvc.SpringServiceNameInstrumentation$SpringServiceNameAdvice.afterInitPropertySources(WebApplicationContext)void/invokeStatic
at java.lang.invoke.MemberName.makeAccessException(MemberName.java:959) ~[?:?]
at java.lang.invoke.MemberName$Factory.resolveOrFail(MemberName.java:1101) ~[?:?]
at java.lang.invoke.MethodHandles$Lookup.resolveOrFail(MethodHandles.java:2030) ~[?:?]
at java.lang.invoke.MethodHandles$Lookup.findStatic(MethodHandles.java:1102) ~[?:?]
at co.elastic.apm.agent.bci.IndyBootstrap.bootstrap(IndyBootstrap.java:290) [?:?]
at jdk.internal.reflect.GeneratedMethodAccessor24.invoke(Unknown Source) ~[?:?]
at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:?]
at java.lang.reflect.Method.invoke(Method.java:566) ~[?:?]
at java.lang.IndyBootstrapDispatcher.bootstrap(IndyBootstrapDispatcher.java:31) [?:?]
at java.lang.invoke.BootstrapMethodInvoker.invoke(BootstrapMethodInvoker.java:138) [?:?]
at java.lang.invoke.CallSite.makeSite(CallSite.java:307) [?:?]
at java.lang.invoke.MethodHandleNatives.linkCallSiteImpl(MethodHandleNatives.java:258) [?:?]
at java.lang.invoke.MethodHandleNatives.linkCallSite(MethodHandleNatives.java:248) [?:?]
at org.springframework.web.context.support.GenericWebApplicationContext.initPropertySources(GenericWebApplicationContext.java:196) [spring-web-5.2.9.RELEASE.jar:5.2.9.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.prepareRefresh(AbstractApplicationContext.java:601) [spring-context-5.2.9.RELEASE.jar:5.2.9.RELEASE]
at org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext.prepareRefresh(AnnotationConfigServletWebServerApplicationContext.java:195) [spring-boot-2.3.4.RELEASE.jar:2.3.4.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:520) [spring-context-5.2.9.RELEASE.jar:5.2.9.RELEASE]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:143) [spring-boot-2.3.4.RELEASE.jar:2.3.4.RELEASE]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:758) [spring-boot-2.3.4.RELEASE.jar:2.3.4.RELEASE]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:750) [spring-boot-2.3.4.RELEASE.jar:2.3.4.RELEASE]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397) [spring-boot-2.3.4.RELEASE.jar:2.3.4.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) [spring-boot-2.3.4.RELEASE.jar:2.3.4.RELEASE]
at org.springframework.boot.web.servlet.support.SpringBootServletInitializer.run(SpringBootServletInitializer.java:173) [spring-boot-2.3.4.RELEASE.jar:2.3.4.RELEASE]
at org.springframework.boot.web.servlet.support.SpringBootServletInitializer.createRootApplicationContext(SpringBootServletInitializer.java:153) [spring-boot-2.3.4.RELEASE.jar:2.3.4.RELEASE]
at org.springframework.boot.web.servlet.support.SpringBootServletInitializer.onStartup(SpringBootServletInitializer.java:95) [spring-boot-2.3.4.RELEASE.jar:2.3.4.RELEASE]
at org.springframework.web.SpringServletContainerInitializer.onStartup(SpringServletContainerInitializer.java:172) [spring-web-5.2.9.RELEASE.jar:5.2.9.RELEASE]
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5139) [catalina.jar:9.0.20]
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183) [catalina.jar:9.0.20]
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:713) [catalina.jar:9.0.20]
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:690) [catalina.jar:9.0.20]
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:705) [catalina.jar:9.0.20]
at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:978) [catalina.jar:9.0.20]
at org.apache.catalina.startup.HostConfig$DeployWar.run(HostConfig.java:1849) [catalina.jar:9.0.20]
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515) [?:?]
at java.util.concurrent.FutureTask.run(FutureTask.java:264) [?:?]
at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75) [tomcat-util.jar:9.0.20]
at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:118) [?:?]
at org.apache.catalina.startup.HostConfig.deployWARs(HostConfig.java:773) [catalina.jar:9.0.20]
at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:427) [catalina.jar:9.0.20]
at org.apache.catalina.startup.HostConfig.start(HostConfig.java:1576) [catalina.jar:9.0.20]
at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:309) [catalina.jar:9.0.20]
at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:123) [catalina.jar:9.0.20]
at org.apache.catalina.util.LifecycleBase.setStateInternal(LifecycleBase.java:423) [catalina.jar:9.0.20]
at org.apache.catalina.util.LifecycleBase.setState(LifecycleBase.java:366) [catalina.jar:9.0.20]
at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:929) [catalina.jar:9.0.20]
at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:841) [catalina.jar:9.0.20]
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183) [catalina.jar:9.0.20]
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1377) [catalina.jar:9.0.20]
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1367) [catalina.jar:9.0.20]
at java.util.concurrent.FutureTask.run(FutureTask.java:264) [?:?]
at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75) [tomcat-util.jar:9.0.20]
at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:140) [?:?]
at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:902) [catalina.jar:9.0.20]
at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:262) [catalina.jar:9.0.20]
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183) [catalina.jar:9.0.20]
at org.apache.catalina.core.StandardService.startInternal(StandardService.java:421) [catalina.jar:9.0.20]
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183) [catalina.jar:9.0.20]
at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:932) [catalina.jar:9.0.20]
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183) [catalina.jar:9.0.20]
at org.apache.catalina.startup.Catalina.start(Catalina.java:633) [catalina.jar:9.0.20]
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:?]
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:?]
at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:?]
at java.lang.reflect.Method.invoke(Method.java:566) ~[?:?]
at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:344) [bootstrap.jar:9.0.20]
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:475) [bootstrap.jar:9.0.20]
Caused by: java.lang.LinkageError: bad method type alias: (WebApplicationContext)void not visible from class co.elastic.apm.agent.springwebmvc.SpringServiceNameInstrumentation$SpringServiceNameAdvice
at java.lang.invoke.MemberName.checkForTypeAlias(MemberName.java:872) ~[?:?]
at java.lang.invoke.MemberName$Factory.resolve(MemberName.java:1074) ~[?:?]
at java.lang.invoke.MemberName$Factory.resolveOrFail(MemberName.java:1098) ~[?:?]
... 64 more
2020-10-21 14:48:59,538 [Thread-16] DEBUG co.elastic.apm.agent.bci.ElasticApmAgent - Type match for instrumentation ServletInstrumentation: ((not(isInterface()) and hasSuperType(erasure(name(equals(javax.servlet.Servlet))))) and not(isInterface())) matches class org.springframework.web.servlet.DispatcherServlet
2020-10-21 14:48:59,538 [Thread-16] TRACE co.elastic.apm.agent.bci.ElasticApmAgent - Advice co.elastic.apm.agent.servlet.ServletInstrumentation is loaded by null
2020-10-21 14:48:59,539 [Thread-16] TRACE co.elastic.apm.agent.bci.ElasticApmAgent - ParallelWebappClassLoader
context: demo1
delegate: false
----------> Parent Classloader:
java.net.URLClassLoader@72cf2de5
can load advice (co.elastic.apm.agent.servlet.ServletInstrumentation): true
...
2020-10-21 14:49:02,381 [main] DEBUG co.elastic.apm.agent.bci.IndyPluginClassLoaderFactory - Creating plugin class loader for ParallelWebappClassLoader
context: demo1
delegate: false
----------> Parent Classloader:
java.net.URLClassLoader@72cf2de5
containing [co.elastic.apm.agent.micrometer.MicrometerMetricsReporter, co.elastic.apm.agent.micrometer.MicrometerInstrumentation, co.elastic.apm.agent.micrometer.MicrometerMeterRegistrySerializer, co.elastic.apm.agent.micrometer.MicrometerMetricsReporter$MeterMapConsumer]
2020-10-21 14:49:02,386 [main] ERROR co.elastic.apm.agent.bci.IndyBootstrap - no such method: co.elastic.apm.agent.micrometer.MicrometerInstrumentation.onExit(MeterRegistry)void/invokeStatic
java.lang.IllegalAccessException: no such method: co.elastic.apm.agent.micrometer.MicrometerInstrumentation.onExit(MeterRegistry)void/invokeStatic
at java.lang.invoke.MemberName.makeAccessException(MemberName.java:959) ~[?:?]
Issue Analytics
- State:
- Created 3 years ago
- Reactions:3
- Comments:6 (6 by maintainers)
Top Results From Across the Web
Trying external-plugin-test on "real setup" fails with "Cannot ...
Trying external-plugin-test on "real setup" fails with "Cannot resolve type description for co.elastic.apm.agent.bci.classloading.LookupExposer".
Read more >Felix Barnsteiner on Twitter: "MethodHandles.publicLookup() fails if ...
IndyBootstrap classloading problem · Issue #1450 · elastic/apm-agent-java. As reported in forum. Problem with 1.18.1(and current master branch) versions.
Read more >JBoss classloading problem - hibernate - Stack Overflow
This particular issue is, I believe, caused by Hibernate trying to auto-locate the Hibernate Validator library on the classpath. The version of Validator ......
Read more >Index (co.elastic.apm:elastic-apm-agent 1.21.0 API) - Javadoc.io
IndyBootstrap. Is called by java.lang. ... ClassLoader) - Method in class co.elastic.apm.agent.impl. ... Information about the originally thrown error.
Read more >java/elastic/apm-agent-java/apm-agent-core/src ... - Program Talk
classloading · methodmatching · DynamicTransformerImpl.java · ElasticApmAgent.java · HelperClassManager.java · HelperHolder.java · IndyBootstrap.java.
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
I have found the moment after which calling
Class.forName("org.springframework.web.context.WebApplicationContext", false, indyPluginClassLoader)
yields aLinkageError
. It happens after calling the native methodMethodHandleNatives.resolve(m, lookupClass, speculativeResolve)
Calling
Class.forName("org.springframework.web.context.WebApplicationContext", false, indyPluginClassLoader)
before this point correctly loads the class. However, when doing so,MethodHandleNatives.resolve
fails with the following exception:java.lang.LinkageError: loader constraint violation: when resolving method 'void co.elastic.apm.agent.springwebmvc.SpringServiceNameInstrumentation$SpringServiceNameAdvice.afterInitPropertySources(org.springframework.web.context.WebApplicationContext)' the class loader 'bootstrap' of the current class, co/elastic/apm/agent/bci/IndyBootstrap, and the class loader co.elastic.apm.agent.bci.classloading.IndyPluginClassLoader @249d9385 for the method's defining class, co/elastic/apm/agent/springwebmvc/SpringServiceNameInstrumentation$SpringServiceNameAdvice, have different Class objects for the type org/springframework/web/context/WebApplicationContext used in the signature (co.elastic.apm.agent.bci.IndyBootstrap is in unnamed module of loader 'bootstrap'; co.elastic.apm.agent.springwebmvc.SpringServiceNameInstrumentation$SpringServiceNameAdvice is in unnamed module of loader co.elastic.apm.agent.bci.classloading.IndyPluginClassLoader @249d9385, parent loader co.elastic.apm.agent.shaded.bytebuddy.dynamic.loading.MultipleParentClassLoader @5d3b5781)
What doesn’t make sense is that the bootstrap class loader does not define
org/springframework/web/context/WebApplicationContext
. The issue seems to be that the lookup is made viaMethodHandles.lookup()
, using the current class as the lookup class. In this case, the lookup class isIndyBootstrap
, which is loaded by the bootstrap classloader (added viaInstrumentation#appendToBootstrapClassLoaderSearch
). What probably happens is that the JVM thinks that classes resolved duringMethodHandleNatives.resolve(m, lookupClass, speculativeResolve)
are loaded by the lookup class’s class loader. When doing another lookup with the same lookup class but in the context of a different web application, it thinksWebApplicationContext
has already been defined in the current class loader hierarchy. This is not true as the bootstrap class loader does not defineWebApplicationContext
.Solution: I’ve found a fix for it. Instead of using
MethodHandles.lookup()
, which uses the caller class as the lookup class, using aMethodHandles.Lookup
instance from a class that’s declared by theIndyPluginClassLoader
helps!https://github.com/elastic/apm-agent-java/blob/4ef35f746671d3fee75c8b3f3462e7dcc92b0089/apm-agent-core/src/main/java/co/elastic/apm/agent/bci/IndyBootstrap.java#L290
Update: PR ready: #1458
I can reproduce the issue now. It happens when deploying two web applications to the same Tomcat server.
During the indy bootstrap, it tries to load
org.springframework.web.context.WebApplicationContext
fromIndyPluginClassLoader
to check if the parameter of the advice method is visible to the advice class.https://github.com/elastic/apm-agent-java/blob/dd90bc45e78dd0e2f2110a7da3f4fd57f7337ce6/apm-agent-plugins/apm-spring-webmvc-plugin/src/main/java/co/elastic/apm/agent/springwebmvc/SpringServiceNameInstrumentation.java#L70-L73
That check goes fine when deploying the first web application. But when deploying a second web app where
SpringServiceNameInstrumentation
is applied (such as the same application under a different context path), that check fails with the following message:loader constraint violation: loader co.elastic.apm.agent.bci.classloading.IndyPluginClassLoader @7041ed62 wants to load interface org.springframework.web.context.WebApplicationContext. A different interface with the same name was previously loaded by org.apache.catalina.loader.ParallelWebappClassLoader @4aff898d. (org.springframework.web.context.WebApplicationContext is in unnamed module of loader org.apache.catalina.loader.ParallelWebappClassLoader @4aff898d, parent loader java.net.URLClassLoader @10027fc9)
Apparently, calling
Class.forName("org.springframework.web.context.WebApplicationContext", false, indyPluginClassLoader)
fails becauseorg.springframework.web.context.WebApplicationContext
is already loaded from a different class loading hierarchy. Interestingly, callingindyPluginClassLoader.loadClass("org.springframework.web.context.WebApplicationContext")
, as well asClass.forName("org.springframework.web.context.WebApplicationContext", false, indyPluginClassLoader.parent)
succeeds.When I’ve tested this on Java 11 (“update 0”), the JVM even crashed with a segfault. The report contains this stack trace: