Skip to content

Commit a2650c9

Browse files
authored
Convert HelperInjectionTest to java (#14910)
1 parent b87e251 commit a2650c9

File tree

2 files changed

+131
-118
lines changed

2 files changed

+131
-118
lines changed

javaagent-tooling/src/test/groovy/io/opentelemetry/javaagent/test/HelperInjectionTest.groovy

Lines changed: 0 additions & 118 deletions
This file was deleted.
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.javaagent.test;
7+
8+
import static io.opentelemetry.instrumentation.test.utils.ClasspathUtils.isClassLoaded;
9+
import static io.opentelemetry.instrumentation.test.utils.GcUtils.awaitGc;
10+
import static java.util.Collections.singletonList;
11+
import static org.assertj.core.api.Assertions.assertThat;
12+
import static org.assertj.core.api.Assertions.assertThatThrownBy;
13+
14+
import io.opentelemetry.javaagent.tooling.AgentInstaller;
15+
import io.opentelemetry.javaagent.tooling.HelperInjector;
16+
import io.opentelemetry.javaagent.tooling.Utils;
17+
import io.opentelemetry.javaagent.tooling.config.EarlyInitAgentConfig;
18+
import java.lang.ref.WeakReference;
19+
import java.net.URL;
20+
import java.net.URLClassLoader;
21+
import java.time.Duration;
22+
import java.util.Collections;
23+
import java.util.concurrent.atomic.AtomicReference;
24+
import net.bytebuddy.agent.ByteBuddyAgent;
25+
import net.bytebuddy.description.type.TypeDescription;
26+
import net.bytebuddy.dynamic.ClassFileLocator;
27+
import net.bytebuddy.dynamic.loading.ClassInjector;
28+
import org.junit.jupiter.api.Test;
29+
30+
@SuppressWarnings("UnnecessaryAsync")
31+
class HelperInjectionTest {
32+
33+
@Test
34+
void helpersInjectedToNonDelegatingClassloader() throws Exception {
35+
URL[] helpersSourceUrls = new URL[1];
36+
helpersSourceUrls[0] = HelperClass.class.getProtectionDomain().getCodeSource().getLocation();
37+
ClassLoader helpersSourceLoader = new URLClassLoader(helpersSourceUrls);
38+
39+
String helperClassName = HelperInjectionTest.class.getPackage().getName() + ".HelperClass";
40+
HelperInjector injector =
41+
new HelperInjector(
42+
"test",
43+
singletonList(helperClassName),
44+
Collections.emptyList(),
45+
helpersSourceLoader,
46+
null);
47+
AtomicReference<URLClassLoader> emptyLoader =
48+
new AtomicReference<>(new URLClassLoader(new URL[0], null));
49+
50+
assertThatThrownBy(() -> emptyLoader.get().loadClass(helperClassName))
51+
.isInstanceOf(ClassNotFoundException.class);
52+
53+
injector.transform(null, null, emptyLoader.get(), null, null);
54+
HelperInjector.loadHelperClass(emptyLoader.get(), helperClassName);
55+
emptyLoader.get().loadClass(helperClassName);
56+
57+
assertThat(isClassLoaded(helperClassName, emptyLoader.get())).isTrue();
58+
// injecting into emptyLoader should not cause helper class to be load in the helper source
59+
// classloader
60+
assertThat(isClassLoaded(helperClassName, helpersSourceLoader)).isFalse();
61+
62+
// references to emptyLoader are gone
63+
emptyLoader.get().close(); // cleanup
64+
WeakReference<URLClassLoader> ref = new WeakReference<>(emptyLoader.get());
65+
emptyLoader.set(null);
66+
67+
awaitGc(ref, Duration.ofSeconds(10));
68+
69+
// HelperInjector doesn't prevent it from being collected
70+
assertThat(ref.get()).isNull();
71+
}
72+
73+
@Test
74+
void helpersInjectedOnBootstrapClassloader() throws Exception {
75+
ByteBuddyAgent.install();
76+
AgentInstaller.installBytebuddyAgent(
77+
ByteBuddyAgent.getInstrumentation(),
78+
this.getClass().getClassLoader(),
79+
EarlyInitAgentConfig.create());
80+
81+
String helperClassName = HelperInjectionTest.class.getPackage().getName() + ".HelperClass";
82+
HelperInjector injector =
83+
new HelperInjector(
84+
"test",
85+
singletonList(helperClassName),
86+
Collections.emptyList(),
87+
this.getClass().getClassLoader(),
88+
ByteBuddyAgent.getInstrumentation());
89+
URLClassLoader bootstrapChild = new URLClassLoader(new URL[0], null);
90+
91+
assertThatThrownBy(() -> bootstrapChild.loadClass(helperClassName))
92+
.isInstanceOf(ClassNotFoundException.class);
93+
94+
ClassLoader bootstrapClassloader = null;
95+
injector.transform(null, null, bootstrapClassloader, null, null);
96+
Class<?> helperClass = bootstrapChild.loadClass(helperClassName);
97+
98+
assertThat(helperClass.getClassLoader()).isEqualTo(bootstrapClassloader);
99+
}
100+
101+
@Test
102+
void checkHardReferencesOnClassInjection() throws Exception {
103+
String helperClassName = HelperInjectionTest.class.getPackage().getName() + ".HelperClass";
104+
105+
// Copied from HelperInjector:
106+
ClassFileLocator locator = ClassFileLocator.ForClassLoader.of(Utils.getAgentClassLoader());
107+
byte[] classBytes = locator.locate(helperClassName).resolve();
108+
TypeDescription typeDesc =
109+
new TypeDescription.Latent(helperClassName, 0, null, Collections.emptyList());
110+
111+
AtomicReference<URLClassLoader> emptyLoader =
112+
new AtomicReference<>(new URLClassLoader(new URL[0], null));
113+
AtomicReference<ClassInjector> injector =
114+
new AtomicReference<>(new ClassInjector.UsingReflection(emptyLoader.get()));
115+
injector.get().inject(Collections.singletonMap(typeDesc, classBytes));
116+
117+
WeakReference<ClassInjector> injectorRef = new WeakReference<>(injector.get());
118+
injector.set(null);
119+
120+
awaitGc(injectorRef, Duration.ofSeconds(10));
121+
122+
assertThat(injectorRef.get()).isNull();
123+
124+
WeakReference<URLClassLoader> loaderRef = new WeakReference<>(emptyLoader.get());
125+
emptyLoader.set(null);
126+
127+
awaitGc(loaderRef, Duration.ofSeconds(10));
128+
129+
assertThat(loaderRef.get()).isNull();
130+
}
131+
}

0 commit comments

Comments
 (0)