Merge pull request #259 from DataDog/ark/type_hunting

Check parent classloaders when resource location fails.
This commit is contained in:
Andrew Kent 2018-03-13 13:51:01 -04:00 committed by GitHub
commit 216cf688a3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 60 additions and 0 deletions

View File

@ -41,6 +41,7 @@ public class AgentInstaller {
.disableClassFormatChanges()
.with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION)
.with(new LoggingListener())
.with(new DDLocationStrategy())
.ignore(nameStartsWith("datadog.trace."))
.or(nameStartsWith("datadog.opentracing."))
.or(nameStartsWith("datadog.slf4j."))

View File

@ -0,0 +1,27 @@
package datadog.trace.agent.tooling;
import java.util.ArrayList;
import java.util.List;
import net.bytebuddy.agent.builder.AgentBuilder;
import net.bytebuddy.dynamic.ClassFileLocator;
import net.bytebuddy.utility.JavaModule;
/**
* Locate resources with the loading classloader. If the loading classloader cannot find the desired
* resource, check up the classloader hierarchy until a resource is found or the bootstrap loader is
* reached.
*/
public class DDLocationStrategy implements AgentBuilder.LocationStrategy {
private static final ClassLoader BOOTSTRAP_RESOURCE_LOCATOR = new ClassLoader(null) {};
@Override
public ClassFileLocator classFileLocator(ClassLoader classLoader, JavaModule javaModule) {
List<ClassFileLocator> locators = new ArrayList<ClassFileLocator>();
while (classLoader != null) {
locators.add(ClassFileLocator.ForClassLoader.of(classLoader));
classLoader = classLoader.getParent();
}
locators.add(ClassFileLocator.ForClassLoader.of(BOOTSTRAP_RESOURCE_LOCATOR));
return new ClassFileLocator.Compound(locators.toArray(new ClassFileLocator[0]));
}
}

View File

@ -0,0 +1,32 @@
package datadog.trace.agent.test
import datadog.trace.agent.tooling.DDLocationStrategy
import net.bytebuddy.agent.builder.AgentBuilder
import net.bytebuddy.dynamic.ClassFileLocator
import spock.lang.Specification
class ResourceLocatingTest extends Specification {
def "finds resources from parent classloader"() {
setup:
final String[] lastLookup = new String[1]
ClassLoader childLoader = new ClassLoader(this.getClass().getClassLoader()) {
@Override
URL getResource(String name) {
lastLookup[0] = name
// do not delegate resource lookup
return findResource(name)
}
}
ClassFileLocator locator = new DDLocationStrategy().classFileLocator(childLoader, null)
ClassFileLocator defaultLocator = AgentBuilder.LocationStrategy.ForClassLoader.STRONG.classFileLocator(childLoader, null)
expect:
locator.locate("java/lang/Object").isResolved()
// lastLookup ensures childLoader was checked before parent for the resource
lastLookup[0] == "java/lang/Object.class"
(lastLookup[0] = null) == null
!defaultLocator.locate("java/lang/Object").isResolved()
lastLookup[0] == "java/lang/Object.class"
}
}