Add agent's classloader to default instrumentation location strategy
The transformer needs the agent's classloader to resolve advice
classes at transform time. Also stop using reflection to register classloads.
MODIFY
dd-java-agent/src/main/java/com/datadoghq/agent/TracingAgent.java
dd-java-agent/src/main/java/com/datadoghq/agent/TracingAgent.java
@@ -25,7 +25,6 @@ import static net.bytebuddy.matcher.ElementMatchers.nameStartsWith;
import dd.trace.Instrumenter;
import java.lang.instrument.Instrumentation;
-import java.lang.reflect.Method;
import java.util.Collections;
import java.util.ServiceLoader;
import java.util.Set;
@@ -40,7 +39,12 @@ import net.bytebuddy.utility.JavaModule;
@Slf4j
public class TracingAgent {
- public static void premain(final String agentArgs, final Instrumentation inst) throws Exception {
+ /** Return the classloader the core agent is running on. */
+ public static ClassLoader getAgentClassLoader() {
+ return TracingAgent.class.getClassLoader();
+ }
+
+ public static void premain(String agentArgs, final Instrumentation inst) throws Exception {
log.debug("Using premain for loading {}", TracingAgent.class.getSimpleName());
addByteBuddy(inst);
AgentRulesManager.initialize();
@@ -111,7 +115,7 @@ public class TracingAgent {
final JavaModule module,
final boolean loaded,
final DynamicType dynamicType) {
- log.debug("Transformed {}", typeDescription);
+ log.debug("Transformed {} -- {}", typeDescription, classLoader);
if (classLoader == null) {
return;
@@ -123,13 +127,9 @@ public class TracingAgent {
initializedClassloaders.add(classLoader);
try {
- final Class<?> rulesManager =
- Class.forName("com.datadoghq.agent.InstrumentationRulesManager", true, classLoader);
- final Method registerClassLoad =
- rulesManager.getDeclaredMethod("registerClassLoad", Object.class);
- registerClassLoad.invoke(null, classLoader);
+ InstrumentationRulesManager.registerClassLoad(classLoader);
} catch (final Throwable e) {
- log.info("ClassLoad Registration for target " + classLoader, e);
+ log.error("Failed ClassLoad Registration for target " + classLoader, e);
}
}
}

MODIFY
dd-java-agent/tooling/src/main/java/dd/trace/DDAdvice.java
dd-java-agent/tooling/src/main/java/dd/trace/DDAdvice.java
package dd.trace;
+import java.lang.reflect.Method;
+import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.agent.builder.AgentBuilder;
+import net.bytebuddy.dynamic.ClassFileLocator;
/** A bytebuddy advice builder with default DataDog settings. */
+@Slf4j
public class DDAdvice extends AgentBuilder.Transformer.ForAdvice {
+ private static ClassLoader AGENT_CLASSLOADER;
+
+ static {
+ try {
+ Class<?> agentClass =
+ DDAdvice.class.getClassLoader().loadClass("com.datadoghq.agent.TracingAgent");
+ Method getAgentClassloaderMethod = agentClass.getMethod("getAgentClassLoader");
+ AGENT_CLASSLOADER = (ClassLoader) getAgentClassloaderMethod.invoke(null);
+ } catch (Throwable t) {
+ log.error("Unable to locate agent classloader. Falling back to System Classloader");
+ AGENT_CLASSLOADER = ClassLoader.getSystemClassLoader();
+ }
+ }
+
public static AgentBuilder.Transformer.ForAdvice create() {
return new DDAdvice()
+ .with(
+ new AgentBuilder.LocationStrategy.Simple(
+ ClassFileLocator.ForClassLoader.of(AGENT_CLASSLOADER)))
.withExceptionHandler(ExceptionHandlers.defaultExceptionHandler());
}

Add agent's classloader to default instrumentation location strategy

The transformer needs the agent's classloader to resolve advice
classes at transform time. Also stop using reflection to register classloads.