Use the bootstrapProxy to load jars.  Better bootstrap url algo
MODIFY
dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/DatadogClassLoader.java
dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/DatadogClassLoader.java
@@ -34,7 +34,6 @@ public class DatadogClassLoader extends URLClassLoader {
// As a workaround, we keep a reference to the bootstrap jar
// to use only for resource lookups.
private final BootstrapClassLoaderProxy bootstrapProxy;
-
/**
* Construct a new DatadogClassLoader
*
@@ -44,25 +43,23 @@ public class DatadogClassLoader extends URLClassLoader {
* 9+.
*/
public DatadogClassLoader(
- final URL bootstrapJarLocation,
- final String internalJarFileName,
- final ClassLoader classloaderForJarResource,
- final ClassLoader parent) {
+ final URL bootstrapJarLocation, final String internalJarFileName, final ClassLoader parent) {
super(new URL[] {}, parent);
bootstrapProxy = new BootstrapClassLoaderProxy(new URL[] {bootstrapJarLocation});
- if (classloaderForJarResource != null) { // Some tests pass null
+ if (internalJarFileName != null) { // some tests pass null
try {
// The fields of the URL are mostly dummy. InternalJarURLHandler is the only important
// field. If extending this class from Classloader instead of URLClassloader required less
// boilerplate it could be used and the need for dummy fields would be reduced
+
final URL internalJarURL =
new URL(
"x-internal-jar",
null,
0,
"/",
- new InternalJarURLHandler(internalJarFileName, classloaderForJarResource));
+ new InternalJarURLHandler(internalJarFileName, bootstrapProxy));
addURL(internalJarURL);
} catch (final MalformedURLException e) {

MODIFY
dd-java-agent/agent-bootstrap/src/test/groovy/datadog/trace/bootstrap/DatadogClassLoaderTest.groovy
dd-java-agent/agent-bootstrap/src/test/groovy/datadog/trace/bootstrap/DatadogClassLoaderTest.groovy
@@ -13,7 +13,7 @@ class DatadogClassLoaderTest extends Specification {
def className1 = 'some/class/Name1'
def className2 = 'some/class/Name2'
final URL loc = getClass().getProtectionDomain().getCodeSource().getLocation()
- final DatadogClassLoader ddLoader = new DatadogClassLoader(loc, null, null, null)
+ final DatadogClassLoader ddLoader = new DatadogClassLoader(loc, null, null)
final Phaser threadHoldLockPhase = new Phaser(2)
final Phaser acquireLockFromMainThreadPhase = new Phaser(2)

MODIFY
dd-java-agent/agent-tooling/src/test/groovy/datadog/trace/agent/test/ClassLoaderMatcherTest.groovy
dd-java-agent/agent-tooling/src/test/groovy/datadog/trace/agent/test/ClassLoaderMatcherTest.groovy
@@ -16,7 +16,7 @@ class ClassLoaderMatcherTest extends Specification {
def "skips agent classloader"() {
setup:
URL root = new URL("file://")
- final URLClassLoader agentLoader = new DatadogClassLoader(root, null, null, null)
+ final URLClassLoader agentLoader = new DatadogClassLoader(root, null, null)
expect:
ClassLoaderMatcher.skipClassLoader().matches(agentLoader)
}

MODIFY
dd-java-agent/src/main/java/datadog/trace/agent/TracingAgent.java
dd-java-agent/src/main/java/datadog/trace/agent/TracingAgent.java
@@ -5,11 +5,14 @@ import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.instrument.Instrumentation;
+import java.lang.management.ManagementFactory;
+import java.lang.management.RuntimeMXBean;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.nio.charset.StandardCharsets;
+import java.security.CodeSource;
import java.util.jar.JarFile;
/** Entry point for initializing the agent. */
@@ -140,10 +143,34 @@ public class TracingAgent {
private static synchronized void installBootstrapJar(final Instrumentation inst)
throws Exception {
if (BOOTSTRAP_URL == null) {
- BOOTSTRAP_URL = TracingAgent.class.getProtectionDomain().getCodeSource().getLocation();
+ File bootstrapJarFile = null;
- // bootstrap jar must be appended before agent classloader is created.
- inst.appendToBootstrapClassLoaderSearch(new JarFile(new File(BOOTSTRAP_URL.toURI())));
+ final CodeSource codeSource = TracingAgent.class.getProtectionDomain().getCodeSource();
+
+ if (codeSource != null) {
+ BOOTSTRAP_URL = codeSource.getLocation();
+ bootstrapJarFile = new File(BOOTSTRAP_URL.toURI());
+ }
+
+ if (bootstrapJarFile == null || bootstrapJarFile.isDirectory()) {
+ // Certain tests (and when running with an IDE) have a folder as the CP
+ // Get the jar from the -javaagent parameter
+ final RuntimeMXBean runtimeMxBean = ManagementFactory.getRuntimeMXBean();
+ for (final String arg : runtimeMxBean.getInputArguments()) {
+ if (arg.startsWith("-javaagent")) {
+ BOOTSTRAP_URL = new URL("file:" + arg.substring(arg.indexOf(":") + 1));
+ bootstrapJarFile = new File(BOOTSTRAP_URL.toURI());
+ break;
+ }
+ }
+
+ if (bootstrapJarFile == null) {
+ throw new Exception(
+ "Unable to install bootstrap jar because agent is running from directory");
+ }
+ }
+
+ inst.appendToBootstrapClassLoaderSearch(new JarFile(bootstrapJarFile));
}
}
@@ -169,11 +196,8 @@ public class TracingAgent {
final Class<?> loaderClass =
ClassLoader.getSystemClassLoader().loadClass("datadog.trace.bootstrap.DatadogClassLoader");
final Constructor constructor =
- loaderClass.getDeclaredConstructor(
- URL.class, String.class, ClassLoader.class, ClassLoader.class);
- return (ClassLoader)
- constructor.newInstance(
- BOOTSTRAP_URL, innerJarFilename, TracingAgent.class.getClassLoader(), agentParent);
+ loaderClass.getDeclaredConstructor(URL.class, String.class, ClassLoader.class);
+ return (ClassLoader) constructor.newInstance(BOOTSTRAP_URL, innerJarFilename, agentParent);
}
private static ClassLoader getPlatformClassLoader()

Use the bootstrapProxy to load jars.  Better bootstrap url algo