diff --git a/dd-java-agent-ittests/src/test/groovy/datadog/trace/agent/integration/classloading/ClassLoadingTest.groovy b/dd-java-agent-ittests/src/test/groovy/datadog/trace/agent/integration/classloading/ClassLoadingTest.groovy index 017127f609..bfb04736f8 100644 --- a/dd-java-agent-ittests/src/test/groovy/datadog/trace/agent/integration/classloading/ClassLoadingTest.groovy +++ b/dd-java-agent-ittests/src/test/groovy/datadog/trace/agent/integration/classloading/ClassLoadingTest.groovy @@ -71,6 +71,7 @@ class ClassLoadingTest extends Specification { then: // ClassToInstrumentChild won't cause an additional getResource() because its TypeDescription is created from transformation bytes. + loader.count > 0 loader.count == countAfterFirstLoad } diff --git a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/ByteBuddyElementMatchers.java b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/ByteBuddyElementMatchers.java index 8cb4d1fb01..c42494ba61 100644 --- a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/ByteBuddyElementMatchers.java +++ b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/ByteBuddyElementMatchers.java @@ -91,7 +91,7 @@ public class ByteBuddyElementMatchers { // in {@code getSuperClass} calls TypeDefinition typeDefinition = target; while (typeDefinition != null) { - if (safeMatches(typeDefinition.asGenericType()) + if (matcher.matches(typeDefinition.asGenericType()) || hasInterface(typeDefinition, checkedInterfaces)) { return true; } @@ -100,15 +100,6 @@ public class ByteBuddyElementMatchers { return false; } - private boolean safeMatches(TypeDescription.Generic target) { - try { - return matcher.matches(target); - } catch (final Exception e) { - log.debug(matcher + ": Exception trying to get match generic type description:", e); - } - return false; - } - private TypeDefinition safeGetSuperClass(final TypeDefinition typeDefinition) { try { return typeDefinition.getSuperClass(); @@ -129,7 +120,7 @@ public class ByteBuddyElementMatchers { final TypeDefinition typeDefinition, final Set checkedInterfaces) { for (final TypeDefinition interfaceType : safeGetInterfaces(typeDefinition)) { if (checkedInterfaces.add(interfaceType.asErasure()) - && (safeMatch(interfaceType.asGenericType()) + && (matcher.matches(interfaceType.asGenericType()) || hasInterface(interfaceType, checkedInterfaces))) { return true; } @@ -137,15 +128,12 @@ public class ByteBuddyElementMatchers { return false; } - private boolean safeMatch(TypeDescription.Generic target) { - try { - return matcher.matches(target); - } catch (final Exception e) { - log.debug(matcher + ": Exception while matching:", e); - } - return false; - } - + /** + * TypeDefinition#getInterfaces() may throw an exception during iteration if an interface is + * absent from the classpath. + * + *

This method exists to allow getting interfaces even if the lookup on one fails. + */ private List safeGetInterfaces(final TypeDefinition typeDefinition) { final List interfaceTypes = new ArrayList<>(); try { diff --git a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/DDCachingPoolStrategy.java b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/DDCachingPoolStrategy.java index cddc0012de..112f9f86ad 100644 --- a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/DDCachingPoolStrategy.java +++ b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/DDCachingPoolStrategy.java @@ -1,5 +1,6 @@ package datadog.trace.agent.tooling; +import static datadog.trace.agent.tooling.ClassLoaderMatcher.BOOTSTRAP_CLASSLOADER; import static net.bytebuddy.agent.builder.AgentBuilder.*; import java.util.Collections; @@ -8,13 +9,27 @@ import java.util.WeakHashMap; import net.bytebuddy.dynamic.ClassFileLocator; import net.bytebuddy.pool.TypePool; +/** + * Custom Pool strategy. + * + *

This is similar to: AgentBuilder.PoolStrategy.WithTypePoolCache.Simple(new + * MapMaker().weakKeys().makeMap()) + * + *

Main differences: + * + *

    + *
  1. Control over the type of the cache. We many not want to use a java.util.ConcurrentMap + *
  2. Use our bootstrap proxy when matching against the bootstrap loader. + *
+ */ public class DDCachingPoolStrategy implements PoolStrategy { private static final Map typePoolCache = Collections.synchronizedMap(new WeakHashMap()); @Override public TypePool typePool(ClassFileLocator classFileLocator, ClassLoader classLoader) { - final ClassLoader key = null == classLoader ? Utils.getBootstrapProxy() : classLoader; + final ClassLoader key = + BOOTSTRAP_CLASSLOADER == classLoader ? Utils.getBootstrapProxy() : classLoader; TypePool.CacheProvider cache = typePoolCache.get(key); if (null == cache) { synchronized (key) {