Skip to content

Commit 388ba8b

Browse files
committed
perf(java-agent): restore the ignore-matcher defaults ByteBuddy provides
1 parent cadebcf commit 388ba8b

1 file changed

Lines changed: 20 additions & 5 deletions

File tree

rollbar-java-agent/src/main/java/com/rollbar/agent/RollbarAgent.java

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import java.util.List;
1313
import java.util.concurrent.atomic.AtomicInteger;
1414
import net.bytebuddy.agent.builder.AgentBuilder;
15+
import net.bytebuddy.description.type.TypeDescription;
1516
import net.bytebuddy.matcher.ElementMatchers;
1617
import net.bytebuddy.utility.JavaModule;
1718

@@ -38,12 +39,26 @@ public static void agentmain(String args, Instrumentation inst) {
3839
}
3940

4041
private static void installInstrumentation(Instrumentation inst) {
41-
// Override ByteBuddy's default which ignores all java.* and javax.* classes,
42-
// so we can instrument JDK HTTP clients (HttpURLConnection, HttpClient).
43-
// We still ignore ByteBuddy's own classes to avoid instrumentation loops.
42+
// Override ByteBuddy's default ignore matcher, which excludes everything loaded by the
43+
// bootstrap and extension classloaders, so we can instrument the JDK HTTP clients
44+
// (HttpURLConnection, HttpClient) that live there.
45+
//
46+
// ignore() replaces that default rather than adding to it, so the rest of the default has to
47+
// be restored by hand. Only the classloader exclusion is deliberately dropped:
48+
// - net.bytebuddy.*/com.rollbar.agent.shaded.* — avoids instrumentation loops.
49+
// - sun.reflect.*/jdk.internal.reflect.* — the reflection machinery an advice body itself
50+
// runs through.
51+
// - isSynthetic() — this matcher is the pre-gate on *every* class load in the JVM. Without
52+
// it, every lambda and dynamic proxy the application ever generates is handed to all four
53+
// type matchers below, two of which run the hasSuperType() hierarchy walk their own
54+
// comments call relatively costly. None of them can ever match a synthetic class, so that
55+
// work is pure overhead — paid application-wide, for the life of the process.
4456
AgentBuilder builder = new AgentBuilder.Default()
45-
.ignore(ElementMatchers.nameStartsWith("net.bytebuddy.")
46-
.or(ElementMatchers.nameStartsWith("com.rollbar.agent.shaded.")))
57+
.ignore(ElementMatchers.<TypeDescription>nameStartsWith("net.bytebuddy.")
58+
.or(ElementMatchers.nameStartsWith("com.rollbar.agent.shaded."))
59+
.or(ElementMatchers.nameStartsWith("sun.reflect."))
60+
.or(ElementMatchers.nameStartsWith("jdk.internal.reflect."))
61+
.or(ElementMatchers.isSynthetic()))
4762
.with(new ErrorReportingListener())
4863
.with(AgentBuilder.InitializationStrategy.NoOp.INSTANCE)
4964
.with(AgentBuilder.TypeStrategy.Default.REDEFINE);

0 commit comments

Comments
 (0)