Skip to content

Commit c461d22

Browse files
authored
Define helper classes in loadClass (#5528)
* Define helper classes in loadClass similarly to regular classes * fix test * spotless * address review comments
1 parent 487a01e commit c461d22

File tree

20 files changed

+334
-368
lines changed

20 files changed

+334
-368
lines changed
Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -30,17 +30,17 @@
3030
import net.bytebuddy.matcher.ElementMatcher;
3131
import org.slf4j.LoggerFactory;
3232

33-
/*
34-
* Some class loaders do not delegate to their parent, so classes in those class loaders
35-
* will not be able to see classes in the bootstrap class loader.
33+
/**
34+
* Some class loaders do not delegate to their parent, so classes in those class loaders will not be
35+
* able to see classes in the bootstrap class loader.
3636
*
37-
* In particular, instrumentation on classes in those class loaders will not be able to see
38-
* the shaded OpenTelemetry API classes in the bootstrap class loader.
37+
* <p>In particular, instrumentation on classes in those class loaders will not be able to see the
38+
* shaded OpenTelemetry API classes in the bootstrap class loader.
3939
*
40-
* This instrumentation forces all class loaders to delegate to the bootstrap class loader
41-
* for the classes that we have put in the bootstrap class loader.
40+
* <p>This instrumentation forces all class loaders to delegate to the bootstrap class loader for
41+
* the classes that we have put in the bootstrap class loader.
4242
*/
43-
public class ClassLoaderInstrumentation implements TypeInstrumentation {
43+
public class BootDelegationInstrumentation implements TypeInstrumentation {
4444

4545
@Override
4646
public ElementMatcher<TypeDescription> typeMatcher() {
@@ -67,7 +67,7 @@ public void transform(TypeTransformer transformer) {
6767
.and(takesArgument(1, boolean.class))))
6868
.and(isPublic().or(isProtected()))
6969
.and(not(isStatic())),
70-
ClassLoaderInstrumentation.class.getName() + "$LoadClassAdvice");
70+
BootDelegationInstrumentation.class.getName() + "$LoadClassAdvice");
7171
}
7272

7373
public static class Holder {

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

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

88
import static java.util.Arrays.asList;
9-
import static java.util.Collections.singletonList;
109

1110
import com.google.auto.service.AutoService;
1211
import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule;
@@ -30,17 +29,11 @@ public boolean isHelperClass(String className) {
3029
return className.equals("io.opentelemetry.javaagent.tooling.Constants");
3130
}
3231

33-
@Override
34-
public List<String> getAdditionalHelperClassNames() {
35-
return singletonList(
36-
"io.opentelemetry.javaagent.instrumentation.internal.classloader.DefineClassUtil");
37-
}
38-
3932
@Override
4033
public List<TypeInstrumentation> typeInstrumentations() {
4134
return asList(
42-
new ClassLoaderInstrumentation(),
43-
new ResourceInjectionInstrumentation(),
44-
new DefineClassInstrumentation());
35+
new BootDelegationInstrumentation(),
36+
new LoadInjectedClassInstrumentation(),
37+
new ResourceInjectionInstrumentation());
4538
}
4639
}

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

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

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

Lines changed: 0 additions & 41 deletions
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
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 static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.extendsClass;
9+
import static net.bytebuddy.matcher.ElementMatchers.isMethod;
10+
import static net.bytebuddy.matcher.ElementMatchers.isProtected;
11+
import static net.bytebuddy.matcher.ElementMatchers.isPublic;
12+
import static net.bytebuddy.matcher.ElementMatchers.isStatic;
13+
import static net.bytebuddy.matcher.ElementMatchers.named;
14+
import static net.bytebuddy.matcher.ElementMatchers.not;
15+
import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
16+
import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
17+
18+
import io.opentelemetry.javaagent.bootstrap.InjectedClassHelper;
19+
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
20+
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
21+
import net.bytebuddy.asm.Advice;
22+
import net.bytebuddy.description.type.TypeDescription;
23+
import net.bytebuddy.matcher.ElementMatcher;
24+
25+
/**
26+
* This instrumentation inserts loading of our injected helper classes at the start of {@code
27+
* ClassLoader.loadClass} method.
28+
*/
29+
public class LoadInjectedClassInstrumentation implements TypeInstrumentation {
30+
31+
@Override
32+
public ElementMatcher<TypeDescription> typeMatcher() {
33+
return extendsClass(named("java.lang.ClassLoader"));
34+
}
35+
36+
@Override
37+
public void transform(TypeTransformer transformer) {
38+
transformer.applyAdviceToMethod(
39+
isMethod()
40+
.and(named("loadClass"))
41+
.and(
42+
takesArguments(1)
43+
.and(takesArgument(0, String.class))
44+
.or(
45+
takesArguments(2)
46+
.and(takesArgument(0, String.class))
47+
.and(takesArgument(1, boolean.class))))
48+
.and(isPublic().or(isProtected()))
49+
.and(not(isStatic())),
50+
LoadInjectedClassInstrumentation.class.getName() + "$LoadClassAdvice");
51+
}
52+
53+
@SuppressWarnings("unused")
54+
public static class LoadClassAdvice {
55+
56+
@Advice.OnMethodEnter(skipOn = Advice.OnNonDefaultValue.class)
57+
public static Class<?> onEnter(
58+
@Advice.This ClassLoader classLoader, @Advice.Argument(0) String name) {
59+
Class<?> helperClass = InjectedClassHelper.loadHelperClass(classLoader, name);
60+
if (helperClass != null) {
61+
return helperClass;
62+
}
63+
64+
return null;
65+
}
66+
67+
@Advice.OnMethodExit(onThrowable = Throwable.class)
68+
public static void onExit(
69+
@Advice.Return(readOnly = false) Class<?> result, @Advice.Enter Class<?> loadedClass) {
70+
if (loadedClass != null) {
71+
result = loadedClass;
72+
}
73+
}
74+
}
75+
}

instrumentation/internal/internal-lambda/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/internal/lambda/LambdaTransformer.java

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

88
import io.opentelemetry.javaagent.bootstrap.ClassFileTransformerHolder;
9-
import io.opentelemetry.javaagent.bootstrap.InjectedHelperClassDetector;
9+
import io.opentelemetry.javaagent.bootstrap.InjectedClassHelper;
1010
import java.lang.instrument.ClassFileTransformer;
1111

1212
/** Helper class for transforming lambda class bytes. */
@@ -31,7 +31,7 @@ private static boolean isJava9() {
3131
@SuppressWarnings("unused")
3232
public static byte[] transform(byte[] classBytes, String slashClassName, Class<?> targetClass) {
3333
// Skip transforming lambdas of injected helper classes.
34-
if (InjectedHelperClassDetector.isHelperClass(targetClass)) {
34+
if (InjectedClassHelper.isHelperClass(targetClass)) {
3535
return classBytes;
3636
}
3737

0 commit comments

Comments
 (0)