diff --git a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/bytebuddy/TypeInfoCache.java b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/bytebuddy/TypeInfoCache.java index c125ddfcad6..0f0d820bffe 100644 --- a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/bytebuddy/TypeInfoCache.java +++ b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/bytebuddy/TypeInfoCache.java @@ -1,8 +1,5 @@ package datadog.trace.agent.tooling.bytebuddy; -import datadog.trace.api.cache.DDCache; -import datadog.trace.api.cache.DDCaches; -import java.lang.ref.WeakReference; import java.net.URL; import java.util.Arrays; import java.util.Objects; @@ -65,12 +62,12 @@ public SharedTypeInfo find(String className) { * * @return previously shared information for the named type */ - public SharedTypeInfo share(String className, ClassLoader loader, URL classFile, T typeInfo) { + public SharedTypeInfo share(String className, int classLoaderId, URL classFile, T typeInfo) { SharedTypeInfo newValue; if (namesAreUnique) { newValue = new SharedTypeInfo<>(className, typeInfo); } else { - newValue = new DisambiguatingTypeInfo<>(className, typeInfo, loader, classFile); + newValue = new DisambiguatingTypeInfo<>(className, typeInfo, classLoaderId, classFile); } int nameHash = className.hashCode(); @@ -117,7 +114,7 @@ public static class SharedTypeInfo { this.typeInfo = typeInfo; } - public boolean sameClassLoader(ClassLoader loader) { + public boolean sameClassLoader(int classLoaderId) { return true; } @@ -132,25 +129,18 @@ public final T get() { /** Includes the classloader and class file resource it originated from. */ static final class DisambiguatingTypeInfo extends SharedTypeInfo { - private static final ClassLoader BOOTSTRAP_LOADER = null; - private static final LoaderId BOOTSTRAP_LOADER_ID = null; - - private static final DDCache loaderIds = - DDCaches.newFixedSizeWeakKeyCache(64); - - private final LoaderId loaderId; + private final int classLoaderId; private final URL classFile; - DisambiguatingTypeInfo(String className, T typeInfo, ClassLoader loader, URL classFile) { + DisambiguatingTypeInfo(String className, T typeInfo, int classLoaderId, URL classFile) { super(className, typeInfo); - this.loaderId = loaderId(loader); + this.classLoaderId = classLoaderId; this.classFile = classFile; } - public boolean sameClassLoader(ClassLoader loader) { - return BOOTSTRAP_LOADER_ID == loaderId - ? BOOTSTRAP_LOADER == loader - : loaderId.sameClassLoader(loader); + @Override + public boolean sameClassLoader(int classLoaderId) { + return this.classLoaderId == classLoaderId; } public boolean sameClassFile(URL classFile) { @@ -159,12 +149,6 @@ public boolean sameClassFile(URL classFile) { && sameClassFile(this.classFile, classFile); } - private static LoaderId loaderId(ClassLoader loader) { - return BOOTSTRAP_LOADER == loader - ? BOOTSTRAP_LOADER_ID - : loaderIds.computeIfAbsent(loader, LoaderId::new); - } - /** Matches class file resources without triggering network lookups. */ private static boolean sameClassFile(URL lhs, URL rhs) { return Objects.equals(lhs.getFile(), rhs.getFile()) @@ -173,18 +157,4 @@ private static boolean sameClassFile(URL lhs, URL rhs) { && Objects.equals(lhs.getProtocol(), rhs.getProtocol()); } } - - /** Supports classloader comparisons without strongly referencing the classloader. */ - static final class LoaderId extends WeakReference { - private final int loaderHash; - - LoaderId(ClassLoader loader) { - super(loader); - this.loaderHash = System.identityHashCode(loader); - } - - boolean sameClassLoader(ClassLoader loader) { - return loaderHash == System.identityHashCode(loader) && loader == get(); - } - } } diff --git a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/bytebuddy/memoize/Memoizer.java b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/bytebuddy/memoize/Memoizer.java index 1ffb277d4c4..6c8d01152ca 100644 --- a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/bytebuddy/memoize/Memoizer.java +++ b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/bytebuddy/memoize/Memoizer.java @@ -239,10 +239,10 @@ static BitSet doMemoize(TypeDescription type, Map localMemos) { // otherwise share result for this location (other locations may have different results) if (namesAreUnique || name.startsWith("java.") || !(type instanceof WithLocation)) { - memos.share(name, null, null, memo); + memos.share(name, 0, null, memo); } else { WithLocation origin = (WithLocation) type; - memos.share(name, origin.getClassLoader(), origin.getClassFile(), memo); + memos.share(name, origin.getClassLoaderId(), origin.getClassFile(), memo); } return memo; @@ -255,7 +255,7 @@ static boolean potentialMatch(String name) { private static boolean sameOrigin(TypeDescription type, SharedTypeInfo sharedMemo) { return !(type instanceof WithLocation) - || sharedMemo.sameClassLoader(((WithLocation) type).getClassLoader()) + || sharedMemo.sameClassLoader(((WithLocation) type).getClassLoaderId()) || sharedMemo.sameClassFile(((WithLocation) type).getClassFile()); } diff --git a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/bytebuddy/outline/TypeFactory.java b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/bytebuddy/outline/TypeFactory.java index 162f3d17555..51650b3d2b2 100644 --- a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/bytebuddy/outline/TypeFactory.java +++ b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/bytebuddy/outline/TypeFactory.java @@ -5,6 +5,7 @@ import static datadog.trace.bootstrap.AgentClassLoading.LOCATING_CLASS; import static net.bytebuddy.dynamic.loading.ClassLoadingStrategy.BOOTSTRAP_LOADER; +import datadog.instrument.utils.ClassLoaderIndex; import datadog.instrument.utils.ClassNameFilter; import datadog.trace.agent.tooling.InstrumenterMetrics; import datadog.trace.agent.tooling.bytebuddy.ClassFileLocators; @@ -101,7 +102,9 @@ final class TypeFactory { ClassLoader originalClassLoader; - ClassLoader classLoader; + ClassLoader currentClassLoader; + + int currentClassLoaderId; ClassFileLocator classFileLocator; @@ -111,8 +114,9 @@ final class TypeFactory { /** Sets the current class-loader context of this type-factory. */ void switchContext(ClassLoader classLoader) { - if (this.classLoader != classLoader || null == classFileLocator) { - this.classLoader = classLoader; + if (currentClassLoader != classLoader || null == classFileLocator) { + currentClassLoader = classLoader; + currentClassLoaderId = -1; // lazily computed classFileLocator = classFileLocator(classLoader); // clear local type cache whenever the class-loader context changes deferredTypes.clear(); @@ -120,7 +124,7 @@ void switchContext(ClassLoader classLoader) { } ClassLoader currentContext() { - return classLoader; + return currentClassLoader; } void beginInstall() { @@ -151,7 +155,7 @@ void beginTransform(String name, byte[] bytecode) { targetBytecode = bytecode; if (installing) { - originalClassLoader = classLoader; + originalClassLoader = currentClassLoader; } } @@ -187,7 +191,8 @@ void endTransform() { private void clearReferences() { if (null != classFileLocator) { - classLoader = null; + currentClassLoader = null; + currentClassLoaderId = -1; classFileLocator = null; deferredTypes.clear(); } @@ -249,13 +254,14 @@ TypeDescription resolveType(LazyType request) { private TypeDescription lookupType( LazyType request, TypeInfoCache types, TypeParser typeParser) { String name = request.name; + int classLoaderId = request.getClassLoaderId(); boolean isOutline = typeParser == outlineTypeParser; long fromTick = InstrumenterMetrics.tick(); // existing type description from same classloader? SharedTypeInfo sharedType = types.find(name); if (null != sharedType - && (name.startsWith("java.") || sharedType.sameClassLoader(classLoader))) { + && (name.startsWith("java.") || sharedType.sameClassLoader(classLoaderId))) { InstrumenterMetrics.reuseTypeDescription(fromTick, isOutline); return sharedType.get(); } @@ -287,7 +293,7 @@ private TypeDescription lookupType( } // share result, whether we found it or not - types.share(name, classLoader, classFile, type); + types.share(name, classLoaderId, classFile, type); return type; } @@ -297,17 +303,17 @@ private TypeDescription loadType(String name, TypeParser typeParser) { LOCATING_CLASS.begin(); try { Class loadedType; - if (BOOTSTRAP_LOADER == classLoader) { + if (BOOTSTRAP_LOADER == currentClassLoader) { loadedType = Class.forName(name, false, BOOTSTRAP_LOADER); - } else if (skipLoadClass(classLoader.getClass().getName())) { + } else if (skipLoadClass(currentClassLoader.getClass().getName())) { return null; // avoid known problematic class-loaders } else { - loadedType = classLoader.loadClass(name); + loadedType = currentClassLoader.loadClass(name); } log.debug( "Direct loadClass type resolution of {} from class loader {} bypasses transformation", name, - classLoader); + currentClassLoader); return typeParser.parse(loadedType); } catch (Throwable ignored) { return null; @@ -333,8 +339,11 @@ final class LazyType extends WithName implements WithLocation { } @Override - public ClassLoader getClassLoader() { - return classLoader; + public int getClassLoaderId() { + if (currentClassLoaderId < 0) { + currentClassLoaderId = ClassLoaderIndex.getClassLoaderKeyId(currentClassLoader); + } + return currentClassLoaderId; } @Override diff --git a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/bytebuddy/outline/WithLocation.java b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/bytebuddy/outline/WithLocation.java index 50f8df880a8..55bde94f0ba 100644 --- a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/bytebuddy/outline/WithLocation.java +++ b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/bytebuddy/outline/WithLocation.java @@ -4,7 +4,7 @@ /** Provides details of where the resolved type was defined. */ public interface WithLocation { - ClassLoader getClassLoader(); + int getClassLoaderId(); URL getClassFile();