Skip to content

Commit 09ea650

Browse files
committed
Properly test glassfish helpers during build-time muzzle checks
The glassfish helpers require package-private access to an interface, so must be injected into the glassfish class-loader. At runtime this is achieved via the instrumentation-based class-injector. We can simulate this for the build-time muzzle checks by granting the same access via reflection.
1 parent ea52d2d commit 09ea650

File tree

1 file changed

+23
-2
lines changed

1 file changed

+23
-2
lines changed

dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/muzzle/MuzzleVersionScanPlugin.java

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import de.thetaphi.forbiddenapis.SuppressForbidden;
99
import java.io.IOException;
1010
import java.io.PrintWriter;
11+
import java.lang.reflect.Method;
1112
import java.util.ArrayList;
1213
import java.util.Arrays;
1314
import java.util.HashSet;
@@ -16,6 +17,7 @@
1617
import java.util.Map;
1718
import java.util.ServiceLoader;
1819
import java.util.Set;
20+
import java.util.function.BiConsumer;
1921
import net.bytebuddy.dynamic.ClassFileLocator;
2022

2123
/**
@@ -75,9 +77,9 @@ public static void assertInstrumentationMuzzled(
7577
// verify helper consistency
7678
final String[] helperClassNames = module.helperClassNames();
7779
if (helperClassNames.length > 0) {
78-
HelperClassLoader helperClassLoader = new HelperClassLoader(testApplicationLoader);
80+
BiConsumer<String, byte[]> injectClassHelper = injectClassHelper(testApplicationLoader);
7981
for (Map.Entry<String, byte[]> helper : createHelperMap(module).entrySet()) {
80-
helperClassLoader.injectClass(helper.getKey(), helper.getValue());
82+
injectClassHelper.accept(helper.getKey(), helper.getValue());
8183
}
8284
}
8385
} catch (final Throwable e) {
@@ -90,6 +92,25 @@ public static void assertInstrumentationMuzzled(
9092
}
9193
}
9294

95+
/** Simulates instrumentation-based access to defineClass feature. */
96+
private static BiConsumer<String, byte[]> injectClassHelper(ClassLoader cl) {
97+
try {
98+
Method defineClass =
99+
ClassLoader.class.getDeclaredMethod(
100+
"defineClass", String.class, byte[].class, int.class, int.class);
101+
defineClass.setAccessible(true);
102+
return (name, bytes) -> {
103+
try {
104+
defineClass.invoke(cl, name, bytes, 0, bytes.length);
105+
} catch (ReflectiveOperationException e) {
106+
throw new RuntimeException(e);
107+
}
108+
};
109+
} catch (ReflectiveOperationException e) {
110+
return new HelperClassLoader(cl)::injectClass;
111+
}
112+
}
113+
93114
// build modules to test while single-threaded to match installer assumptions
94115
private static synchronized List<InstrumenterModule> toBeTested(
95116
ClassLoader instrumentationLoader, String muzzleDirective) {

0 commit comments

Comments
 (0)