Use the bootstrapProxy to load jars. Better bootstrap url algo
This commit is contained in:
parent
cf98110991
commit
273feafa94
|
@ -34,7 +34,6 @@ public class DatadogClassLoader extends URLClassLoader {
|
||||||
// As a workaround, we keep a reference to the bootstrap jar
|
// As a workaround, we keep a reference to the bootstrap jar
|
||||||
// to use only for resource lookups.
|
// to use only for resource lookups.
|
||||||
private final BootstrapClassLoaderProxy bootstrapProxy;
|
private final BootstrapClassLoaderProxy bootstrapProxy;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a new DatadogClassLoader
|
* Construct a new DatadogClassLoader
|
||||||
*
|
*
|
||||||
|
@ -44,25 +43,23 @@ public class DatadogClassLoader extends URLClassLoader {
|
||||||
* 9+.
|
* 9+.
|
||||||
*/
|
*/
|
||||||
public DatadogClassLoader(
|
public DatadogClassLoader(
|
||||||
final URL bootstrapJarLocation,
|
final URL bootstrapJarLocation, final String internalJarFileName, final ClassLoader parent) {
|
||||||
final String internalJarFileName,
|
|
||||||
final ClassLoader classloaderForJarResource,
|
|
||||||
final ClassLoader parent) {
|
|
||||||
super(new URL[] {}, parent);
|
super(new URL[] {}, parent);
|
||||||
bootstrapProxy = new BootstrapClassLoaderProxy(new URL[] {bootstrapJarLocation});
|
bootstrapProxy = new BootstrapClassLoaderProxy(new URL[] {bootstrapJarLocation});
|
||||||
|
|
||||||
if (classloaderForJarResource != null) { // Some tests pass null
|
if (internalJarFileName != null) { // some tests pass null
|
||||||
try {
|
try {
|
||||||
// The fields of the URL are mostly dummy. InternalJarURLHandler is the only important
|
// 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
|
// 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
|
// boilerplate it could be used and the need for dummy fields would be reduced
|
||||||
|
|
||||||
final URL internalJarURL =
|
final URL internalJarURL =
|
||||||
new URL(
|
new URL(
|
||||||
"x-internal-jar",
|
"x-internal-jar",
|
||||||
null,
|
null,
|
||||||
0,
|
0,
|
||||||
"/",
|
"/",
|
||||||
new InternalJarURLHandler(internalJarFileName, classloaderForJarResource));
|
new InternalJarURLHandler(internalJarFileName, bootstrapProxy));
|
||||||
|
|
||||||
addURL(internalJarURL);
|
addURL(internalJarURL);
|
||||||
} catch (final MalformedURLException e) {
|
} catch (final MalformedURLException e) {
|
||||||
|
|
|
@ -13,7 +13,7 @@ class DatadogClassLoaderTest extends Specification {
|
||||||
def className1 = 'some/class/Name1'
|
def className1 = 'some/class/Name1'
|
||||||
def className2 = 'some/class/Name2'
|
def className2 = 'some/class/Name2'
|
||||||
final URL loc = getClass().getProtectionDomain().getCodeSource().getLocation()
|
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 threadHoldLockPhase = new Phaser(2)
|
||||||
final Phaser acquireLockFromMainThreadPhase = new Phaser(2)
|
final Phaser acquireLockFromMainThreadPhase = new Phaser(2)
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ class ClassLoaderMatcherTest extends Specification {
|
||||||
def "skips agent classloader"() {
|
def "skips agent classloader"() {
|
||||||
setup:
|
setup:
|
||||||
URL root = new URL("file://")
|
URL root = new URL("file://")
|
||||||
final URLClassLoader agentLoader = new DatadogClassLoader(root, null, null, null)
|
final URLClassLoader agentLoader = new DatadogClassLoader(root, null, null)
|
||||||
expect:
|
expect:
|
||||||
ClassLoaderMatcher.skipClassLoader().matches(agentLoader)
|
ClassLoaderMatcher.skipClassLoader().matches(agentLoader)
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,11 +5,14 @@ import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.lang.instrument.Instrumentation;
|
import java.lang.instrument.Instrumentation;
|
||||||
|
import java.lang.management.ManagementFactory;
|
||||||
|
import java.lang.management.RuntimeMXBean;
|
||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.security.CodeSource;
|
||||||
import java.util.jar.JarFile;
|
import java.util.jar.JarFile;
|
||||||
|
|
||||||
/** Entry point for initializing the agent. */
|
/** Entry point for initializing the agent. */
|
||||||
|
@ -140,10 +143,34 @@ public class TracingAgent {
|
||||||
private static synchronized void installBootstrapJar(final Instrumentation inst)
|
private static synchronized void installBootstrapJar(final Instrumentation inst)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
if (BOOTSTRAP_URL == null) {
|
if (BOOTSTRAP_URL == null) {
|
||||||
BOOTSTRAP_URL = TracingAgent.class.getProtectionDomain().getCodeSource().getLocation();
|
File bootstrapJarFile = null;
|
||||||
|
|
||||||
// bootstrap jar must be appended before agent classloader is created.
|
final CodeSource codeSource = TracingAgent.class.getProtectionDomain().getCodeSource();
|
||||||
inst.appendToBootstrapClassLoaderSearch(new JarFile(new File(BOOTSTRAP_URL.toURI())));
|
|
||||||
|
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 =
|
final Class<?> loaderClass =
|
||||||
ClassLoader.getSystemClassLoader().loadClass("datadog.trace.bootstrap.DatadogClassLoader");
|
ClassLoader.getSystemClassLoader().loadClass("datadog.trace.bootstrap.DatadogClassLoader");
|
||||||
final Constructor constructor =
|
final Constructor constructor =
|
||||||
loaderClass.getDeclaredConstructor(
|
loaderClass.getDeclaredConstructor(URL.class, String.class, ClassLoader.class);
|
||||||
URL.class, String.class, ClassLoader.class, ClassLoader.class);
|
return (ClassLoader) constructor.newInstance(BOOTSTRAP_URL, innerJarFilename, agentParent);
|
||||||
return (ClassLoader)
|
|
||||||
constructor.newInstance(
|
|
||||||
BOOTSTRAP_URL, innerJarFilename, TracingAgent.class.getClassLoader(), agentParent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ClassLoader getPlatformClassLoader()
|
private static ClassLoader getPlatformClassLoader()
|
||||||
|
|
Loading…
Reference in New Issue