Skip to content

Commit d0b00e0

Browse files
author
Andrew Kent
committed
Inject all map holder classes into the bootstrap
1 parent 5f0f6f1 commit d0b00e0

8 files changed

Lines changed: 159 additions & 259 deletions

File tree

dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/context/MapBackedProvider.java

Lines changed: 2 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
import java.lang.reflect.Method;
1111
import java.util.HashMap;
1212
import java.util.Map;
13-
import java.util.Set;
1413
import java.util.UUID;
1514
import java.util.concurrent.atomic.AtomicReference;
1615
import jdk.internal.org.objectweb.asm.ClassWriter;
@@ -112,7 +111,8 @@ public DynamicType.Builder<?> transform(
112111
return injector.transform(
113112
builder,
114113
typeDescription,
115-
findClassLoaderForMapHolderInjection(classLoader),
114+
// dynamic map classes will always go to the bootstrap
115+
BOOTSTRAP_CLASSLOADER,
116116
module);
117117
}
118118
});
@@ -259,49 +259,6 @@ public void visitLdcInsn(Object value) {
259259
};
260260
}
261261

262-
/**
263-
* Find the topmost classloader in the classloader hierarchy (beginning from startingLoader) which
264-
* can load all user classes defined in the instrumentation context store.
265-
*/
266-
private ClassLoader findClassLoaderForMapHolderInjection(final ClassLoader startingLoader) {
267-
final Set<String> userClassNames = instrumenter.contextStore().keySet();
268-
ClassLoader lastGoodLoader = startingLoader;
269-
ClassLoader searchLoader = startingLoader;
270-
// search up the classloader hierarchy for a classloader which can see all user classes
271-
while (true) {
272-
log.debug(
273-
"{}: Searching for classloader to inject dynamic context map: {}",
274-
instrumenter,
275-
searchLoader);
276-
if (searchLoader == BOOTSTRAP_CLASSLOADER) {
277-
searchLoader = Utils.getBootstrapProxy();
278-
}
279-
boolean allClassesFound = true;
280-
for (final String userClassName : userClassNames) {
281-
if (searchLoader.getResource(Utils.getResourceName(userClassName)) == null) {
282-
allClassesFound = false;
283-
break;
284-
}
285-
}
286-
if (!allClassesFound) {
287-
// current searchLoader can't see resources. Use last good classloader.
288-
break;
289-
}
290-
lastGoodLoader = searchLoader;
291-
if (searchLoader == Utils.getBootstrapProxy()) {
292-
// all classloaders can see resources. Use bootstrap
293-
searchLoader = BOOTSTRAP_CLASSLOADER;
294-
lastGoodLoader = BOOTSTRAP_CLASSLOADER;
295-
break;
296-
}
297-
searchLoader = searchLoader.getParent();
298-
}
299-
300-
log.debug(
301-
"{}: Found classloader to inject dynamic context map: {}", instrumenter, lastGoodLoader);
302-
return lastGoodLoader;
303-
}
304-
305262
private Map<String, byte[]> dynamicClasses() {
306263
return createOrGetDynamicClasses();
307264
}

dd-java-agent/agent-tooling/src/test/groovy/datadog/trace/agent/test/context/MapBackedProviderTest.groovy

Lines changed: 0 additions & 162 deletions
This file was deleted.

dd-java-agent/agent-tooling/src/test/java/datadog/trace/agent/test/context/BadClassToRemap.java

Lines changed: 0 additions & 20 deletions
This file was deleted.

dd-java-agent/agent-tooling/src/test/java/datadog/trace/agent/test/context/ClassToRemap.java

Lines changed: 0 additions & 32 deletions
This file was deleted.
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package context
2+
3+
import datadog.trace.agent.test.AgentTestRunner
4+
import datadog.trace.agent.test.TestUtils
5+
import net.bytebuddy.utility.JavaModule
6+
7+
import java.lang.ref.WeakReference
8+
9+
class MapBackedProviderTest extends AgentTestRunner {
10+
11+
def setupSpec() {
12+
assert new UserClass1().isInstrumented()
13+
}
14+
15+
@Override
16+
boolean onInstrumentationError(
17+
final String typeName,
18+
final ClassLoader classLoader,
19+
final JavaModule module,
20+
final boolean loaded,
21+
final Throwable throwable) {
22+
// UserClass2 asserts on incorrect api usage. Error expected.
23+
return !(typeName.equals(UserClass2.getName()) && throwable.getMessage().startsWith("Incorrect Context Api Usage detected."))
24+
}
25+
26+
def "correct api usage stores state in map"() {
27+
when:
28+
UserClass1 instance1 = new UserClass1()
29+
UserClass1 instance2 = new UserClass1()
30+
instance1.incrementContextCount()
31+
32+
then:
33+
instance1.incrementContextCount() == 2
34+
instance2.incrementContextCount() == 1
35+
}
36+
37+
def "backing map should not create strong refs to user instances"() {
38+
when:
39+
UserClass1 instance = new UserClass1()
40+
final int count = instance.incrementContextCount()
41+
WeakReference<UserClass1> instanceRef = new WeakReference(instance)
42+
instance = null
43+
TestUtils.awaitGC(instanceRef)
44+
45+
then:
46+
instanceRef.get() == null
47+
count == 1
48+
}
49+
50+
def "incorrect api usage fails at class load time"() {
51+
expect:
52+
!new UserClass2().isInstrumented()
53+
}
54+
}

0 commit comments

Comments
 (0)