Skip to content

Commit 81f3795

Browse files
authored
Use inline advice in class loader instrumentation (#13613)
1 parent 8c56645 commit 81f3795

File tree

6 files changed

+61
-46
lines changed

6 files changed

+61
-46
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.javaagent.instrumentation.internal.classloader;
7+
8+
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
9+
import io.opentelemetry.javaagent.tooling.Utils;
10+
import io.opentelemetry.javaagent.tooling.bytebuddy.ExceptionHandlers;
11+
import net.bytebuddy.agent.builder.AgentBuilder;
12+
import net.bytebuddy.asm.Advice;
13+
import net.bytebuddy.description.method.MethodDescription;
14+
import net.bytebuddy.matcher.ElementMatcher;
15+
16+
class AdviceUtil {
17+
private static final Advice.WithCustomMapping adviceMapping =
18+
Advice.withCustomMapping()
19+
.with(new Advice.AssignReturned.Factory().withSuppressed(Throwable.class));
20+
21+
static void applyInlineAdvice(
22+
TypeTransformer transformer, ElementMatcher<MethodDescription> matcher, String adviceClass) {
23+
transformer.applyTransformer(
24+
new AgentBuilder.Transformer.ForAdvice(adviceMapping)
25+
.include(Utils.getBootstrapProxy(), Utils.getAgentClassLoader())
26+
.withExceptionHandler(ExceptionHandlers.defaultExceptionHandler())
27+
.advice(matcher, adviceClass));
28+
}
29+
30+
private AdviceUtil() {}
31+
}

instrumentation/internal/internal-class-loader/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/internal/classloader/BootDelegationInstrumentation.java

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
package io.opentelemetry.javaagent.instrumentation.internal.classloader;
77

88
import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.extendsClass;
9+
import static io.opentelemetry.javaagent.instrumentation.internal.classloader.AdviceUtil.applyInlineAdvice;
910
import static net.bytebuddy.matcher.ElementMatchers.isMethod;
1011
import static net.bytebuddy.matcher.ElementMatchers.isProtected;
1112
import static net.bytebuddy.matcher.ElementMatchers.isPublic;
@@ -19,9 +20,6 @@
1920
import io.opentelemetry.javaagent.bootstrap.CallDepth;
2021
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
2122
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
22-
import io.opentelemetry.javaagent.tooling.Utils;
23-
import io.opentelemetry.javaagent.tooling.bytebuddy.ExceptionHandlers;
24-
import net.bytebuddy.agent.builder.AgentBuilder;
2523
import net.bytebuddy.asm.Advice;
2624
import net.bytebuddy.description.method.MethodDescription;
2725
import net.bytebuddy.description.type.TypeDescription;
@@ -62,12 +60,7 @@ public void transform(TypeTransformer transformer) {
6260
.and(isPublic().or(isProtected()))
6361
.and(not(isStatic()));
6462
// Inline instrumentation to prevent problems with invokedynamic-recursion
65-
transformer.applyTransformer(
66-
new AgentBuilder.Transformer.ForAdvice()
67-
.include(Utils.getBootstrapProxy(), Utils.getAgentClassLoader())
68-
.withExceptionHandler(ExceptionHandlers.defaultExceptionHandler())
69-
.advice(
70-
methodMatcher, BootDelegationInstrumentation.class.getName() + "$LoadClassAdvice"));
63+
applyInlineAdvice(transformer, methodMatcher, this.getClass().getName() + "$LoadClassAdvice");
7164
}
7265

7366
@SuppressWarnings("unused")

instrumentation/internal/internal-class-loader/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/internal/classloader/DefineClassInstrumentation.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
package io.opentelemetry.javaagent.instrumentation.internal.classloader;
77

8+
import static io.opentelemetry.javaagent.instrumentation.internal.classloader.AdviceUtil.applyInlineAdvice;
89
import static net.bytebuddy.matcher.ElementMatchers.named;
910
import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
1011

@@ -27,16 +28,18 @@ public ElementMatcher<TypeDescription> typeMatcher() {
2728

2829
@Override
2930
public void transform(TypeTransformer transformer) {
30-
transformer.applyAdviceToMethod(
31+
applyInlineAdvice(
32+
transformer,
3133
named("defineClass")
3234
.and(
3335
takesArguments(
3436
String.class, byte[].class, int.class, int.class, ProtectionDomain.class)),
35-
DefineClassInstrumentation.class.getName() + "$DefineClassAdvice");
36-
transformer.applyAdviceToMethod(
37+
this.getClass().getName() + "$DefineClassAdvice");
38+
applyInlineAdvice(
39+
transformer,
3740
named("defineClass")
3841
.and(takesArguments(String.class, ByteBuffer.class, ProtectionDomain.class)),
39-
DefineClassInstrumentation.class.getName() + "$DefineClassWithThreeArgsAdvice");
42+
this.getClass().getName() + "$DefineClassWithThreeArgsAdvice");
4043
}
4144

4245
@SuppressWarnings("unused")

instrumentation/internal/internal-class-loader/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/internal/classloader/LoadInjectedClassInstrumentation.java

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
package io.opentelemetry.javaagent.instrumentation.internal.classloader;
77

88
import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.extendsClass;
9+
import static io.opentelemetry.javaagent.instrumentation.internal.classloader.AdviceUtil.applyInlineAdvice;
910
import static net.bytebuddy.matcher.ElementMatchers.isMethod;
1011
import static net.bytebuddy.matcher.ElementMatchers.isProtected;
1112
import static net.bytebuddy.matcher.ElementMatchers.isPublic;
@@ -18,9 +19,6 @@
1819
import io.opentelemetry.javaagent.bootstrap.InjectedClassHelper;
1920
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
2021
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
21-
import io.opentelemetry.javaagent.tooling.Utils;
22-
import io.opentelemetry.javaagent.tooling.bytebuddy.ExceptionHandlers;
23-
import net.bytebuddy.agent.builder.AgentBuilder;
2422
import net.bytebuddy.asm.Advice;
2523
import net.bytebuddy.description.method.MethodDescription;
2624
import net.bytebuddy.description.type.TypeDescription;
@@ -52,13 +50,7 @@ public void transform(TypeTransformer transformer) {
5250
.and(isPublic().or(isProtected()))
5351
.and(not(isStatic()));
5452
// Inline instrumentation to prevent problems with invokedynamic-recursion
55-
transformer.applyTransformer(
56-
new AgentBuilder.Transformer.ForAdvice()
57-
.include(Utils.getBootstrapProxy(), Utils.getAgentClassLoader())
58-
.withExceptionHandler(ExceptionHandlers.defaultExceptionHandler())
59-
.advice(
60-
methodMatcher,
61-
LoadInjectedClassInstrumentation.class.getName() + "$LoadClassAdvice"));
53+
applyInlineAdvice(transformer, methodMatcher, this.getClass().getName() + "$LoadClassAdvice");
6254
}
6355

6456
@SuppressWarnings("unused")

instrumentation/internal/internal-class-loader/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/internal/classloader/ResourceInjectionInstrumentation.java

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
package io.opentelemetry.javaagent.instrumentation.internal.classloader;
77

88
import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.extendsClass;
9-
import static net.bytebuddy.matcher.ElementMatchers.isMethod;
9+
import static io.opentelemetry.javaagent.instrumentation.internal.classloader.AdviceUtil.applyInlineAdvice;
1010
import static net.bytebuddy.matcher.ElementMatchers.named;
1111
import static net.bytebuddy.matcher.ElementMatchers.returns;
1212
import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
@@ -37,24 +37,20 @@ public ElementMatcher<TypeDescription> typeMatcher() {
3737

3838
@Override
3939
public void transform(TypeTransformer transformer) {
40-
transformer.applyAdviceToMethod(
41-
isMethod()
42-
.and(named("getResource"))
43-
.and(takesArguments(String.class))
44-
.and(returns(URL.class)),
45-
ResourceInjectionInstrumentation.class.getName() + "$GetResourceAdvice");
46-
transformer.applyAdviceToMethod(
47-
isMethod()
48-
.and(named("getResources"))
49-
.and(takesArguments(String.class))
50-
.and(returns(Enumeration.class)),
51-
ResourceInjectionInstrumentation.class.getName() + "$GetResourcesAdvice");
52-
transformer.applyAdviceToMethod(
53-
isMethod()
54-
.and(named("getResourceAsStream"))
40+
applyInlineAdvice(
41+
transformer,
42+
named("getResource").and(takesArguments(String.class)).and(returns(URL.class)),
43+
this.getClass().getName() + "$GetResourceAdvice");
44+
applyInlineAdvice(
45+
transformer,
46+
named("getResources").and(takesArguments(String.class)).and(returns(Enumeration.class)),
47+
this.getClass().getName() + "$GetResourcesAdvice");
48+
applyInlineAdvice(
49+
transformer,
50+
named("getResourceAsStream")
5551
.and(takesArguments(String.class))
5652
.and(returns(InputStream.class)),
57-
ResourceInjectionInstrumentation.class.getName() + "$GetResourceAsStreamAdvice");
53+
this.getClass().getName() + "$GetResourceAsStreamAdvice");
5854
}
5955

6056
@SuppressWarnings("unused")

javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/AgentInstaller.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
import java.util.HashMap;
5757
import java.util.List;
5858
import java.util.Map;
59+
import java.util.Objects;
5960
import java.util.logging.LogManager;
6061
import java.util.logging.Logger;
6162
import java.util.stream.Stream;
@@ -225,12 +226,11 @@ private static void installEarlyInstrumentation(
225226

226227
AgentBuilder.Identified.Extendable extendableAgentBuilder =
227228
agentBuilder
228-
.ignore(
229-
target ->
230-
// turn off after instrumentation is installed, exclude classes in
231-
// java.lang.invoke to avoid circularity when bootstrapping indy instrumentation
232-
instrumentationInstalled
233-
|| target.getTypeName().startsWith("java.lang.invoke."))
229+
// ignore classes that are not in boot loader, this also ignores classes in our agent
230+
// loader
231+
.ignore(any(), Objects::nonNull)
232+
// turn off after instrumentation is installed
233+
.or(target -> instrumentationInstalled)
234234
.type(none())
235235
.transform(
236236
(builder, typeDescription, classLoader, module, protectionDomain) -> builder);

0 commit comments

Comments
 (0)