Remove AgentTestRunner custom classloader.
BytebuddyAgent install already handles class retransformation, make the custom classloader redundant.
This commit is contained in:
parent
1c08933bc7
commit
d315f43dad
|
@ -4,19 +4,12 @@ import com.datadoghq.agent.AgentInstaller;
|
||||||
import com.datadoghq.trace.DDTracer;
|
import com.datadoghq.trace.DDTracer;
|
||||||
import com.datadoghq.trace.writer.ListWriter;
|
import com.datadoghq.trace.writer.ListWriter;
|
||||||
import io.opentracing.Tracer;
|
import io.opentracing.Tracer;
|
||||||
import java.io.IOException;
|
|
||||||
import java.lang.instrument.ClassFileTransformer;
|
import java.lang.instrument.ClassFileTransformer;
|
||||||
import java.lang.instrument.Instrumentation;
|
import java.lang.instrument.Instrumentation;
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import net.bytebuddy.agent.ByteBuddyAgent;
|
import net.bytebuddy.agent.ByteBuddyAgent;
|
||||||
import net.bytebuddy.dynamic.ClassFileLocator;
|
|
||||||
import org.junit.AfterClass;
|
import org.junit.AfterClass;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
import org.junit.runner.notification.RunNotifier;
|
|
||||||
import org.junit.runners.model.InitializationError;
|
|
||||||
import org.spockframework.runtime.Sputnik;
|
|
||||||
import org.spockframework.runtime.model.SpecMetadata;
|
import org.spockframework.runtime.model.SpecMetadata;
|
||||||
import spock.lang.Specification;
|
import spock.lang.Specification;
|
||||||
|
|
||||||
|
@ -35,7 +28,6 @@ import spock.lang.Specification;
|
||||||
* in an initialized state.
|
* in an initialized state.
|
||||||
* </ul>
|
* </ul>
|
||||||
*/
|
*/
|
||||||
@RunWith(AgentTestRunner.SpockRunner.class)
|
|
||||||
@SpecMetadata(filename = "AgentTestRunner.java", line = 0)
|
@SpecMetadata(filename = "AgentTestRunner.java", line = 0)
|
||||||
public abstract class AgentTestRunner extends Specification {
|
public abstract class AgentTestRunner extends Specification {
|
||||||
/**
|
/**
|
||||||
|
@ -75,76 +67,4 @@ public abstract class AgentTestRunner extends Specification {
|
||||||
instrumentation.removeTransformer(activeTransformer);
|
instrumentation.removeTransformer(activeTransformer);
|
||||||
activeTransformer = null;
|
activeTransformer = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: Remove SpockRunner and custom classload logic
|
|
||||||
|
|
||||||
public static class SpockRunner extends Sputnik {
|
|
||||||
private final InstrumentationClassLoader customLoader;
|
|
||||||
|
|
||||||
public SpockRunner(Class<?> clazz)
|
|
||||||
throws InitializationError, NoSuchFieldException, SecurityException,
|
|
||||||
IllegalArgumentException, IllegalAccessException {
|
|
||||||
super(shadowTestClass(clazz));
|
|
||||||
// access the classloader created in shadowTestClass above
|
|
||||||
Field clazzField = Sputnik.class.getDeclaredField("clazz");
|
|
||||||
try {
|
|
||||||
clazzField.setAccessible(true);
|
|
||||||
customLoader =
|
|
||||||
(InstrumentationClassLoader) ((Class<?>) clazzField.get(this)).getClassLoader();
|
|
||||||
} finally {
|
|
||||||
clazzField.setAccessible(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Shadow the test class with bytes loaded by InstrumentationClassLoader
|
|
||||||
private static Class<?> shadowTestClass(final Class<?> clazz) {
|
|
||||||
try {
|
|
||||||
InstrumentationClassLoader customLoader =
|
|
||||||
new InstrumentationClassLoader(SpockRunner.class.getClassLoader());
|
|
||||||
return customLoader.shadow(clazz);
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new IllegalStateException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Replace the context class loader for each test with InstrumentationClassLoader
|
|
||||||
@Override
|
|
||||||
public void run(final RunNotifier notifier) {
|
|
||||||
final ClassLoader contextLoader = Thread.currentThread().getContextClassLoader();
|
|
||||||
try {
|
|
||||||
Thread.currentThread().setContextClassLoader(customLoader);
|
|
||||||
super.run(notifier);
|
|
||||||
} finally {
|
|
||||||
Thread.currentThread().setContextClassLoader(contextLoader);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A ClassLoader which retransforms classes unseen by the installed agent. With the exception of
|
|
||||||
* shadowed classes, this class
|
|
||||||
*/
|
|
||||||
private static class InstrumentationClassLoader extends java.lang.ClassLoader {
|
|
||||||
final ClassLoader parent;
|
|
||||||
|
|
||||||
public InstrumentationClassLoader(ClassLoader parent) {
|
|
||||||
super(parent);
|
|
||||||
this.parent = parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Forcefully inject the bytes of clazz into this classloader. */
|
|
||||||
public Class<?> shadow(Class<?> clazz) throws IOException {
|
|
||||||
final ClassFileLocator locator = ClassFileLocator.ForClassLoader.of(clazz.getClassLoader());
|
|
||||||
final byte[] classBytes = locator.locate(clazz.getName()).resolve();
|
|
||||||
|
|
||||||
Class<?> shadowed = this.defineClass(clazz.getName(), classBytes, 0, classBytes.length);
|
|
||||||
return shadowed;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
|
|
||||||
// TODO: If already loaded and not seen by agent: do a retransform.
|
|
||||||
return parent.loadClass(name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue