Open SylvainJuge opened 2 years ago
As it was really easy to reproduce with a local WL setup, I spend some time on fixing this. When this happens, it prevents the agent from communicating with APM server, thus the impact could be quite high.
It does not happen when the agent starts without delay because the agent is fast enough to create the URL
object before the WL server overrides the default handler.
The issue is generic and happens whenever the default URL protocol handlers are overridden in the JVM.
Unfortunately, the fix provided by #2429 proved to not be reliable and had to be reverted.
Class.forName
Class.forName
.An alternative approach is required here:
URL
constructor to be able to call the Class.forName
from a place where it's OK.URL
objects before the instrumentation is available.URLStreamHandler
implementations themselves to gracefully delegate to default implementations when another implementation is registered. This might not be possible if the implementation class could not be loaded from the bootstrap/agent classpath.Also, the chosen implementation should try to avoid relying on implementation details as it is required to work on JDK from 7 to 17.
A few more details on why fixing this might be tedious:
URLStreamHandler
is registered, the URL
instances created will use the default implementation, so when the agent is configured through -javaagent
it might have time to create the URL
object early with the default. However if configuration is changed afterwards, or if the agent startup is delayed, the agent is unable to communicate properly.URLStreamHandler
can be registered through multiple ways: through ServiceLoader
SPI, through system properties and programatically through URL.setURLStreamHandlerFactory
(javadoc) which can be called only once for the whole JVM process lifetimeURLStreamHandler
has been resolved for a given protocol, it is stored in a map, so the factory is called only once per protocol.URL
objects created by the agent could be an option, for example agenthttp
and agenthttps
. Doing so should be done without calling URL.setURLStreamHandlerFactory
as it might not be called anymore afterwards, so maybe the URL
constructor is still the right place to do that, also we should still find a way to delegate to default URLStreamHandler
implementations with the "right" protocol afterwards.SecurityManager
might prevent calling URL
constructor with a non-default handler, so maybe intercepting the end of the constructor instead of the beginning could be relevant. Also, checking a thread-local state might be used instead of a marker implementation of URLStreamHandler
passed through arguments, and intercepting the end of the constructor execution to alter its returned value would allow to avoid the SecurityManager
check.Another alternative suggested by @eyalkoren : try to always create the URL
object from the application classloader instead of the agent CL: this CL is expected to have access to the Weblogic classes and dependencies.
Discovered with
1.28.4
agent + Weblogic 12c12.2.1.3.0
, very likely to impact other versions as well.Description
The following stack trace is visible in Weblogic standard output when the agent starts
Impact
Low, does not prevent the agent to send data to APM serverCould be quite high, as it works "by accident" of the agent being fast on JVM startup, and it can prevent the agent to communicate with APM server. Would also happen systematically when using runtime attach.