diff --git a/instrumentation/internal/internal-class-loader/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/internal/classloader/AdviceUtil.java b/instrumentation/internal/internal-class-loader/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/internal/classloader/AdviceUtil.java new file mode 100644 index 000000000000..c860547f9c6a --- /dev/null +++ b/instrumentation/internal/internal-class-loader/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/internal/classloader/AdviceUtil.java @@ -0,0 +1,31 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.internal.classloader; + +import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; +import io.opentelemetry.javaagent.tooling.Utils; +import io.opentelemetry.javaagent.tooling.bytebuddy.ExceptionHandlers; +import net.bytebuddy.agent.builder.AgentBuilder; +import net.bytebuddy.asm.Advice; +import net.bytebuddy.description.method.MethodDescription; +import net.bytebuddy.matcher.ElementMatcher; + +class AdviceUtil { + private static final Advice.WithCustomMapping adviceMapping = + Advice.withCustomMapping() + .with(new Advice.AssignReturned.Factory().withSuppressed(Throwable.class)); + + static void applyInlineAdvice( + TypeTransformer transformer, ElementMatcher matcher, String adviceClass) { + transformer.applyTransformer( + new AgentBuilder.Transformer.ForAdvice(adviceMapping) + .include(Utils.getBootstrapProxy(), Utils.getAgentClassLoader()) + .withExceptionHandler(ExceptionHandlers.defaultExceptionHandler()) + .advice(matcher, adviceClass)); + } + + private AdviceUtil() {} +} diff --git a/instrumentation/internal/internal-class-loader/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/internal/classloader/BootDelegationInstrumentation.java b/instrumentation/internal/internal-class-loader/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/internal/classloader/BootDelegationInstrumentation.java index a18778912b6a..e40cea1c41f3 100644 --- a/instrumentation/internal/internal-class-loader/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/internal/classloader/BootDelegationInstrumentation.java +++ b/instrumentation/internal/internal-class-loader/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/internal/classloader/BootDelegationInstrumentation.java @@ -6,6 +6,7 @@ package io.opentelemetry.javaagent.instrumentation.internal.classloader; import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.extendsClass; +import static io.opentelemetry.javaagent.instrumentation.internal.classloader.AdviceUtil.applyInlineAdvice; import static net.bytebuddy.matcher.ElementMatchers.isMethod; import static net.bytebuddy.matcher.ElementMatchers.isProtected; import static net.bytebuddy.matcher.ElementMatchers.isPublic; @@ -19,9 +20,6 @@ import io.opentelemetry.javaagent.bootstrap.CallDepth; import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; -import io.opentelemetry.javaagent.tooling.Utils; -import io.opentelemetry.javaagent.tooling.bytebuddy.ExceptionHandlers; -import net.bytebuddy.agent.builder.AgentBuilder; import net.bytebuddy.asm.Advice; import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.type.TypeDescription; @@ -62,12 +60,7 @@ public void transform(TypeTransformer transformer) { .and(isPublic().or(isProtected())) .and(not(isStatic())); // Inline instrumentation to prevent problems with invokedynamic-recursion - transformer.applyTransformer( - new AgentBuilder.Transformer.ForAdvice() - .include(Utils.getBootstrapProxy(), Utils.getAgentClassLoader()) - .withExceptionHandler(ExceptionHandlers.defaultExceptionHandler()) - .advice( - methodMatcher, BootDelegationInstrumentation.class.getName() + "$LoadClassAdvice")); + applyInlineAdvice(transformer, methodMatcher, this.getClass().getName() + "$LoadClassAdvice"); } @SuppressWarnings("unused") diff --git a/instrumentation/internal/internal-class-loader/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/internal/classloader/DefineClassInstrumentation.java b/instrumentation/internal/internal-class-loader/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/internal/classloader/DefineClassInstrumentation.java index 20ca23bb8b0d..612fc815be85 100644 --- a/instrumentation/internal/internal-class-loader/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/internal/classloader/DefineClassInstrumentation.java +++ b/instrumentation/internal/internal-class-loader/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/internal/classloader/DefineClassInstrumentation.java @@ -5,6 +5,7 @@ package io.opentelemetry.javaagent.instrumentation.internal.classloader; +import static io.opentelemetry.javaagent.instrumentation.internal.classloader.AdviceUtil.applyInlineAdvice; import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.takesArguments; @@ -27,16 +28,18 @@ public ElementMatcher typeMatcher() { @Override public void transform(TypeTransformer transformer) { - transformer.applyAdviceToMethod( + applyInlineAdvice( + transformer, named("defineClass") .and( takesArguments( String.class, byte[].class, int.class, int.class, ProtectionDomain.class)), - DefineClassInstrumentation.class.getName() + "$DefineClassAdvice"); - transformer.applyAdviceToMethod( + this.getClass().getName() + "$DefineClassAdvice"); + applyInlineAdvice( + transformer, named("defineClass") .and(takesArguments(String.class, ByteBuffer.class, ProtectionDomain.class)), - DefineClassInstrumentation.class.getName() + "$DefineClassWithThreeArgsAdvice"); + this.getClass().getName() + "$DefineClassWithThreeArgsAdvice"); } @SuppressWarnings("unused") diff --git a/instrumentation/internal/internal-class-loader/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/internal/classloader/LoadInjectedClassInstrumentation.java b/instrumentation/internal/internal-class-loader/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/internal/classloader/LoadInjectedClassInstrumentation.java index fcf37f8a24b6..81aea69de8b7 100644 --- a/instrumentation/internal/internal-class-loader/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/internal/classloader/LoadInjectedClassInstrumentation.java +++ b/instrumentation/internal/internal-class-loader/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/internal/classloader/LoadInjectedClassInstrumentation.java @@ -6,6 +6,7 @@ package io.opentelemetry.javaagent.instrumentation.internal.classloader; import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.extendsClass; +import static io.opentelemetry.javaagent.instrumentation.internal.classloader.AdviceUtil.applyInlineAdvice; import static net.bytebuddy.matcher.ElementMatchers.isMethod; import static net.bytebuddy.matcher.ElementMatchers.isProtected; import static net.bytebuddy.matcher.ElementMatchers.isPublic; @@ -18,9 +19,6 @@ import io.opentelemetry.javaagent.bootstrap.InjectedClassHelper; import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; -import io.opentelemetry.javaagent.tooling.Utils; -import io.opentelemetry.javaagent.tooling.bytebuddy.ExceptionHandlers; -import net.bytebuddy.agent.builder.AgentBuilder; import net.bytebuddy.asm.Advice; import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.type.TypeDescription; @@ -52,13 +50,7 @@ public void transform(TypeTransformer transformer) { .and(isPublic().or(isProtected())) .and(not(isStatic())); // Inline instrumentation to prevent problems with invokedynamic-recursion - transformer.applyTransformer( - new AgentBuilder.Transformer.ForAdvice() - .include(Utils.getBootstrapProxy(), Utils.getAgentClassLoader()) - .withExceptionHandler(ExceptionHandlers.defaultExceptionHandler()) - .advice( - methodMatcher, - LoadInjectedClassInstrumentation.class.getName() + "$LoadClassAdvice")); + applyInlineAdvice(transformer, methodMatcher, this.getClass().getName() + "$LoadClassAdvice"); } @SuppressWarnings("unused") diff --git a/instrumentation/internal/internal-class-loader/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/internal/classloader/ResourceInjectionInstrumentation.java b/instrumentation/internal/internal-class-loader/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/internal/classloader/ResourceInjectionInstrumentation.java index 65076ce645d7..cd83896bca2b 100644 --- a/instrumentation/internal/internal-class-loader/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/internal/classloader/ResourceInjectionInstrumentation.java +++ b/instrumentation/internal/internal-class-loader/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/internal/classloader/ResourceInjectionInstrumentation.java @@ -6,7 +6,7 @@ package io.opentelemetry.javaagent.instrumentation.internal.classloader; import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.extendsClass; -import static net.bytebuddy.matcher.ElementMatchers.isMethod; +import static io.opentelemetry.javaagent.instrumentation.internal.classloader.AdviceUtil.applyInlineAdvice; import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.returns; import static net.bytebuddy.matcher.ElementMatchers.takesArguments; @@ -37,24 +37,20 @@ public ElementMatcher typeMatcher() { @Override public void transform(TypeTransformer transformer) { - transformer.applyAdviceToMethod( - isMethod() - .and(named("getResource")) - .and(takesArguments(String.class)) - .and(returns(URL.class)), - ResourceInjectionInstrumentation.class.getName() + "$GetResourceAdvice"); - transformer.applyAdviceToMethod( - isMethod() - .and(named("getResources")) - .and(takesArguments(String.class)) - .and(returns(Enumeration.class)), - ResourceInjectionInstrumentation.class.getName() + "$GetResourcesAdvice"); - transformer.applyAdviceToMethod( - isMethod() - .and(named("getResourceAsStream")) + applyInlineAdvice( + transformer, + named("getResource").and(takesArguments(String.class)).and(returns(URL.class)), + this.getClass().getName() + "$GetResourceAdvice"); + applyInlineAdvice( + transformer, + named("getResources").and(takesArguments(String.class)).and(returns(Enumeration.class)), + this.getClass().getName() + "$GetResourcesAdvice"); + applyInlineAdvice( + transformer, + named("getResourceAsStream") .and(takesArguments(String.class)) .and(returns(InputStream.class)), - ResourceInjectionInstrumentation.class.getName() + "$GetResourceAsStreamAdvice"); + this.getClass().getName() + "$GetResourceAsStreamAdvice"); } @SuppressWarnings("unused") diff --git a/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/AgentInstaller.java b/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/AgentInstaller.java index d84226806580..5a08597845f1 100644 --- a/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/AgentInstaller.java +++ b/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/AgentInstaller.java @@ -56,6 +56,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.logging.LogManager; import java.util.logging.Logger; import java.util.stream.Stream; @@ -225,12 +226,11 @@ private static void installEarlyInstrumentation( AgentBuilder.Identified.Extendable extendableAgentBuilder = agentBuilder - .ignore( - target -> - // turn off after instrumentation is installed, exclude classes in - // java.lang.invoke to avoid circularity when bootstrapping indy instrumentation - instrumentationInstalled - || target.getTypeName().startsWith("java.lang.invoke.")) + // ignore classes that are not in boot loader, this also ignores classes in our agent + // loader + .ignore(any(), Objects::nonNull) + // turn off after instrumentation is installed + .or(target -> instrumentationInstalled) .type(none()) .transform( (builder, typeDescription, classLoader, module, protectionDomain) -> builder);