Transform lambda classes (#4182)

* Transform lambda classes

* improve comment
This commit is contained in:
Lauri Tulmin 2021-09-24 19:52:15 +03:00 committed by GitHub
parent ae7ad4b7e8
commit 559cdcbbee
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 283 additions and 119 deletions

View File

@ -15,11 +15,8 @@ import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
import io.opentelemetry.javaagent.instrumentation.api.ContextStore;
import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext;
import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge;
import io.opentelemetry.javaagent.instrumentation.api.concurrent.CallableWrapper;
import io.opentelemetry.javaagent.instrumentation.api.concurrent.ExecutorAdviceHelper;
import io.opentelemetry.javaagent.instrumentation.api.concurrent.PropagatedContext;
import io.opentelemetry.javaagent.instrumentation.api.concurrent.RunnableWrapper;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.concurrent.Callable;
@ -74,7 +71,6 @@ public class JavaExecutorInstrumentation extends AbstractExecutorInstrumentation
@Advice.Argument(value = 0, readOnly = false) Runnable task) {
Context context = Java8BytecodeBridge.currentContext();
if (ExecutorAdviceHelper.shouldPropagateContext(context, task)) {
task = RunnableWrapper.wrapIfNeeded(task);
ContextStore<Runnable, PropagatedContext> contextStore =
InstrumentationContext.get(Runnable.class, PropagatedContext.class);
return ExecutorAdviceHelper.attachContextToTask(context, contextStore, task);
@ -119,7 +115,6 @@ public class JavaExecutorInstrumentation extends AbstractExecutorInstrumentation
@Advice.Argument(value = 0, readOnly = false) Runnable task) {
Context context = Java8BytecodeBridge.currentContext();
if (ExecutorAdviceHelper.shouldPropagateContext(context, task)) {
task = RunnableWrapper.wrapIfNeeded(task);
ContextStore<Runnable, PropagatedContext> contextStore =
InstrumentationContext.get(Runnable.class, PropagatedContext.class);
return ExecutorAdviceHelper.attachContextToTask(context, contextStore, task);
@ -149,7 +144,6 @@ public class JavaExecutorInstrumentation extends AbstractExecutorInstrumentation
@Advice.Argument(value = 0, readOnly = false) Callable<?> task) {
Context context = Java8BytecodeBridge.currentContext();
if (ExecutorAdviceHelper.shouldPropagateContext(context, task)) {
task = CallableWrapper.wrapIfNeeded(task);
ContextStore<Callable<?>, PropagatedContext> contextStore =
InstrumentationContext.get(Callable.class, PropagatedContext.class);
return ExecutorAdviceHelper.attachContextToTask(context, contextStore, task);
@ -181,21 +175,15 @@ public class JavaExecutorInstrumentation extends AbstractExecutorInstrumentation
return Collections.emptyList();
}
Collection<Callable<?>> wrappedTasks = new ArrayList<>(tasks.size());
Context context = Java8BytecodeBridge.currentContext();
for (Callable<?> task : tasks) {
if (ExecutorAdviceHelper.shouldPropagateContext(context, task)) {
Callable<?> newTask = CallableWrapper.wrapIfNeeded(task);
wrappedTasks.add(newTask);
ContextStore<Callable<?>, PropagatedContext> contextStore =
InstrumentationContext.get(Callable.class, PropagatedContext.class);
ExecutorAdviceHelper.attachContextToTask(context, contextStore, newTask);
} else {
// note that task may be null here
wrappedTasks.add(task);
ExecutorAdviceHelper.attachContextToTask(context, contextStore, task);
}
}
tasks = wrappedTasks;
// returning tasks and not propagatedContexts to avoid allocating another list just for an
// edge case (exception)
return tasks;
@ -203,8 +191,7 @@ public class JavaExecutorInstrumentation extends AbstractExecutorInstrumentation
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
public static void submitExit(
@Advice.Enter Collection<? extends Callable<?>> wrappedTasks,
@Advice.Thrown Throwable throwable) {
@Advice.Enter Collection<? extends Callable<?>> tasks, @Advice.Thrown Throwable throwable) {
/*
Note1: invokeAny doesn't return any futures so all we need to do for it
is to make sure we close all scopes in case of an exception.
@ -215,7 +202,7 @@ public class JavaExecutorInstrumentation extends AbstractExecutorInstrumentation
(according to ExecutorService docs and AbstractExecutorService code)
*/
if (throwable != null) {
for (Callable<?> task : wrappedTasks) {
for (Callable<?> task : tasks) {
if (task != null) {
ContextStore<Callable<?>, PropagatedContext> contextStore =
InstrumentationContext.get(Callable.class, PropagatedContext.class);

View File

@ -16,7 +16,6 @@ import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext;
import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge;
import io.opentelemetry.javaagent.instrumentation.api.concurrent.ExecutorAdviceHelper;
import io.opentelemetry.javaagent.instrumentation.api.concurrent.PropagatedContext;
import io.opentelemetry.javaagent.instrumentation.api.concurrent.RunnableWrapper;
import java.util.concurrent.Executor;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.type.TypeDescription;
@ -55,7 +54,6 @@ public class GuavaListenableFutureInstrumentation implements TypeInstrumentation
@Advice.Argument(value = 0, readOnly = false) Runnable task) {
Context context = Java8BytecodeBridge.currentContext();
if (ExecutorAdviceHelper.shouldPropagateContext(context, task)) {
task = RunnableWrapper.wrapIfNeeded(task);
ContextStore<Runnable, PropagatedContext> contextStore =
InstrumentationContext.get(Runnable.class, PropagatedContext.class);
return ExecutorAdviceHelper.attachContextToTask(context, contextStore, task);

View File

@ -0,0 +1,9 @@
plugins {
id("otel.javaagent-instrumentation")
}
dependencies {
compileOnly(project(":javaagent-bootstrap"))
testImplementation(project(":javaagent-bootstrap"))
}

View File

@ -0,0 +1,118 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.internal.lambda;
import static net.bytebuddy.matcher.ElementMatchers.named;
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
import net.bytebuddy.asm.AsmVisitorWrapper;
import net.bytebuddy.description.field.FieldDescription;
import net.bytebuddy.description.field.FieldList;
import net.bytebuddy.description.method.MethodList;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.implementation.Implementation;
import net.bytebuddy.jar.asm.ClassVisitor;
import net.bytebuddy.jar.asm.ClassWriter;
import net.bytebuddy.jar.asm.MethodVisitor;
import net.bytebuddy.jar.asm.Opcodes;
import net.bytebuddy.jar.asm.Type;
import net.bytebuddy.matcher.ElementMatcher;
import net.bytebuddy.pool.TypePool;
public class InnerClassLambdaMetafactoryInstrumentation implements TypeInstrumentation {
@Override
public ElementMatcher<TypeDescription> typeMatcher() {
return named("java.lang.invoke.InnerClassLambdaMetafactory");
}
@Override
public void transform(TypeTransformer transformer) {
transformer.applyTransformer(
(builder, typeDescription, classLoader, module) ->
builder.visit(
new AsmVisitorWrapper() {
@Override
public int mergeWriter(int flags) {
return flags | ClassWriter.COMPUTE_MAXS;
}
@Override
public int mergeReader(int flags) {
return flags;
}
@Override
public ClassVisitor wrap(
TypeDescription instrumentedType,
ClassVisitor classVisitor,
Implementation.Context implementationContext,
TypePool typePool,
FieldList<FieldDescription.InDefinedShape> fields,
MethodList<?> methods,
int writerFlags,
int readerFlags) {
return new MetaFactoryClassVisitor(
classVisitor, instrumentedType.getInternalName());
}
}));
}
private static class MetaFactoryClassVisitor extends ClassVisitor {
private final String slashClassName;
MetaFactoryClassVisitor(ClassVisitor cv, String slashClassName) {
super(Opcodes.ASM7, cv);
this.slashClassName = slashClassName;
}
@Override
public MethodVisitor visitMethod(
int access, String name, String descriptor, String signature, String[] exceptions) {
MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions);
// The version of InnerClassLambdaMetafactory used in first version of jdk8 can be seen at
// https://hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java
// Depending on jdk version we instrument either spinInnerClass or generateInnerClass.
// We look for a call to ASM ClassWriter.toByteArray() and insert our lambda class
// transformation after it so that defining lambda class will proceed with replaced bytecode.
// This transformation uses ASM instead of Byte-Buddy advice because advice allows adding
// code to the start and end of the method, but here we are modifying a call in the middle of
// the method.
if (("spinInnerClass".equals(name) || "generateInnerClass".equals(name))
&& "()Ljava/lang/Class;".equals(descriptor)) {
mv =
new MethodVisitor(api, mv) {
@Override
public void visitMethodInsn(
int opcode, String owner, String name, String descriptor, boolean isInterface) {
super.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
// if current instruction is a call to ASM ClassWriter.toByteArray() insert call to
// our lambda transformer
if (opcode == Opcodes.INVOKEVIRTUAL
&& "toByteArray".equals(name)
&& "()[B".equals(descriptor)) {
mv.visitVarInsn(Opcodes.ALOAD, 0);
mv.visitFieldInsn(
Opcodes.GETFIELD, slashClassName, "lambdaClassName", "Ljava/lang/String;");
mv.visitVarInsn(Opcodes.ALOAD, 0);
// targetClass is used to get the ClassLoader where lambda class will be defined
mv.visitFieldInsn(
Opcodes.GETFIELD, slashClassName, "targetClass", "Ljava/lang/Class;");
mv.visitMethodInsn(
Opcodes.INVOKESTATIC,
Type.getInternalName(LambdaTransformer.class),
"transform",
"([BLjava/lang/String;Ljava/lang/Class;)[B",
false);
}
}
};
}
return mv;
}
}
}

View File

@ -0,0 +1,39 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.internal.lambda;
import static java.util.Collections.singletonList;
import com.google.auto.service.AutoService;
import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule;
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
import java.util.List;
@AutoService(InstrumentationModule.class)
public class LambdaInstrumentationModule extends InstrumentationModule {
public LambdaInstrumentationModule() {
super("internal-lambda");
}
@Override
public boolean defaultEnabled() {
// internal instrumentations are always enabled by default
return true;
}
@Override
public List<String> getMuzzleHelperClassNames() {
// this instrumentation uses ASM not ByteBuddy so muzzle doesn't automatically add helper
// classes
return singletonList(
"io.opentelemetry.javaagent.instrumentation.internal.lambda.LambdaTransformer");
}
@Override
public List<TypeInstrumentation> typeInstrumentations() {
return singletonList(new InnerClassLambdaMetafactoryInstrumentation());
}
}

View File

@ -0,0 +1,38 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.internal.lambda;
import io.opentelemetry.javaagent.bootstrap.ClassFileTransformerHolder;
import java.lang.instrument.ClassFileTransformer;
/** Helper class for transforming lambda class bytes. */
public final class LambdaTransformer {
private LambdaTransformer() {}
/**
* Called from {@code java.lang.invoke.InnerClassLambdaMetafactory} to transform lambda class
* bytes.
*/
public static byte[] transform(byte[] classBytes, String slashClassName, Class<?> targetClass) {
ClassFileTransformer transformer = ClassFileTransformerHolder.getClassFileTransformer();
if (transformer != null) {
try {
byte[] result =
transformer.transform(
targetClass.getClassLoader(), slashClassName, null, null, classBytes);
if (result != null) {
return result;
}
} catch (Throwable throwable) {
// sun.instrument.TransformerManager catches Throwable from ClassFileTransformer and ignores
// it, we do the same.
}
}
return classBytes;
}
}

View File

@ -0,0 +1,21 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
import io.opentelemetry.instrumentation.test.AgentInstrumentationSpecification
import io.opentelemetry.javaagent.bootstrap.FieldBackedContextStoreAppliedMarker
class LambdaInstrumentationTest extends AgentInstrumentationSpecification {
def "test transform Runnable lambda"() {
setup:
Runnable runnable = TestLambda.makeRunnable()
expect:
// RunnableInstrumentation adds a ContextStore to all implementors of Runnable. If lambda class
// is transformed then it must have context store marker interface.
runnable instanceof FieldBackedContextStoreAppliedMarker
!FieldBackedContextStoreAppliedMarker.isAssignableFrom(Runnable)
}
}

View File

@ -0,0 +1,10 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
public class TestLambda {
static Runnable makeRunnable() {
return () -> {};
}
}

View File

@ -17,7 +17,6 @@ import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext;
import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge;
import io.opentelemetry.javaagent.instrumentation.api.concurrent.ExecutorAdviceHelper;
import io.opentelemetry.javaagent.instrumentation.api.concurrent.PropagatedContext;
import io.opentelemetry.javaagent.instrumentation.api.concurrent.RunnableWrapper;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher;
@ -44,7 +43,6 @@ public class JettyQueuedThreadPoolInstrumentation implements TypeInstrumentation
@Advice.Argument(value = 0, readOnly = false) Runnable task) {
Context context = Java8BytecodeBridge.currentContext();
if (ExecutorAdviceHelper.shouldPropagateContext(context, task)) {
task = RunnableWrapper.wrapIfNeeded(task);
ContextStore<Runnable, PropagatedContext> contextStore =
InstrumentationContext.get(Runnable.class, PropagatedContext.class);
return ExecutorAdviceHelper.attachContextToTask(context, contextStore, task);

View File

@ -5,7 +5,6 @@
import io.opentelemetry.api.trace.SpanKind
import io.opentelemetry.instrumentation.test.AgentInstrumentationSpecification
import io.opentelemetry.javaagent.instrumentation.jetty.JavaLambdaMaker
import org.eclipse.jetty.util.thread.QueuedThreadPool
import static org.junit.Assume.assumeTrue

View File

@ -3,8 +3,6 @@
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.jetty;
public class JavaLambdaMaker {
@SuppressWarnings("FunctionalExpressionCanBeFolded")

View File

@ -19,7 +19,6 @@ import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext;
import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge;
import io.opentelemetry.javaagent.instrumentation.api.concurrent.ExecutorAdviceHelper;
import io.opentelemetry.javaagent.instrumentation.api.concurrent.PropagatedContext;
import io.opentelemetry.javaagent.instrumentation.api.concurrent.RunnableWrapper;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher;
@ -50,7 +49,6 @@ public class SimpleAsyncTaskExecutorInstrumentation implements TypeInstrumentati
@Advice.Argument(value = 0, readOnly = false) Runnable task) {
Context context = Java8BytecodeBridge.currentContext();
if (ExecutorAdviceHelper.shouldPropagateContext(context, task)) {
task = RunnableWrapper.wrapIfNeeded(task);
ContextStore<Runnable, PropagatedContext> contextStore =
InstrumentationContext.get(Runnable.class, PropagatedContext.class);
return ExecutorAdviceHelper.attachContextToTask(context, contextStore, task);

View File

@ -0,0 +1,28 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.bootstrap;
import java.lang.instrument.ClassFileTransformer;
/**
* Holder for {@link ClassFileTransformer} used by the instrumentation. Calling transform on this
* class file transformer processes given bytes the same way as they would be processed during
* loading of the class.
*/
public final class ClassFileTransformerHolder {
private static volatile ClassFileTransformer classFileTransformer;
public static ClassFileTransformer getClassFileTransformer() {
return classFileTransformer;
}
public static void setClassFileTransformer(ClassFileTransformer transformer) {
classFileTransformer = transformer;
}
private ClassFileTransformerHolder() {}
}

View File

@ -1,41 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.api.concurrent;
import java.util.concurrent.Callable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* This is used to wrap lambda callables since currently we cannot instrument them.
*
* <p>FIXME: We should remove this once https://github.com/raphw/byte-buddy/issues/558 is fixed
*/
public final class CallableWrapper<T> implements Callable<T> {
private static final Logger logger = LoggerFactory.getLogger(CallableWrapper.class);
public static Callable<?> wrapIfNeeded(Callable<?> task) {
// We wrap only lambdas' anonymous classes and if given object has not already been wrapped.
// Anonymous classes have '/' in class name which is not allowed in 'normal' classes.
if (task.getClass().getName().contains("/") && !(task instanceof CallableWrapper)) {
logger.debug("Wrapping callable task {}", task);
return new CallableWrapper(task);
}
return task;
}
private final Callable<T> callable;
private CallableWrapper(Callable<T> callable) {
this.callable = callable;
}
@Override
public T call() throws Exception {
return callable.call();
}
}

View File

@ -1,40 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.api.concurrent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* This is used to wrap lambda runnables since currently we cannot instrument them.
*
* <p>FIXME: We should remove this once https://github.com/raphw/byte-buddy/issues/558 is fixed
*/
public final class RunnableWrapper implements Runnable {
private static final Logger logger = LoggerFactory.getLogger(RunnableWrapper.class);
public static Runnable wrapIfNeeded(Runnable task) {
// We wrap only lambdas' anonymous classes and if given object has not already been wrapped.
// Anonymous classes have '/' in class name which is not allowed in 'normal' classes.
if (task.getClass().getName().contains("/") && !(task instanceof RunnableWrapper)) {
logger.debug("Wrapping runnable task {}", task);
return new RunnableWrapper(task);
}
return task;
}
private final Runnable runnable;
private RunnableWrapper(Runnable runnable) {
this.runnable = runnable;
}
@Override
public void run() {
runnable.run();
}
}

View File

@ -16,6 +16,7 @@ import io.opentelemetry.context.ContextStorage;
import io.opentelemetry.context.Scope;
import io.opentelemetry.instrumentation.api.config.Config;
import io.opentelemetry.javaagent.bootstrap.AgentClassLoader;
import io.opentelemetry.javaagent.bootstrap.ClassFileTransformerHolder;
import io.opentelemetry.javaagent.extension.AgentExtension;
import io.opentelemetry.javaagent.extension.AgentListener;
import io.opentelemetry.javaagent.extension.bootstrap.BootstrapPackagesConfigurer;
@ -143,9 +144,6 @@ public class AgentInstaller {
.with(AgentTooling.poolStrategy())
.with(new ClassLoadListener())
.with(AgentTooling.locationStrategy(Utils.getBootstrapProxy()));
// FIXME: we cannot enable it yet due to BB/JVM bug, see
// https://github.com/raphw/byte-buddy/issues/558
// .with(AgentBuilder.LambdaInstrumentationStrategy.ENABLED)
agentBuilder = configureIgnoredTypes(config, agentBuilder);
@ -178,6 +176,7 @@ public class AgentInstaller {
logger.debug("Installed {} extension(s)", numberOfLoadedExtensions);
ResettableClassFileTransformer resettableClassFileTransformer = agentBuilder.installOn(inst);
ClassFileTransformerHolder.setClassFileTransformer(resettableClassFileTransformer);
runAfterAgentListeners(agentListeners, config);
return resettableClassFileTransformer;
}

View File

@ -76,7 +76,9 @@ public class AdditionalLibraryIgnoredTypesConfigurer implements IgnoredTypesConf
.ignoreClass("org.springframework.data.")
.allowClass("org.springframework.data.repository.core.support.RepositoryFactorySupport")
.allowClass("org.springframework.data.convert.ClassGeneratingEntityInstantiator$")
.allowClass("org.springframework.data.jpa.repository.config.InspectionClassLoader");
.allowClass("org.springframework.data.jpa.repository.config.InspectionClassLoader")
.allowClass(
"org.springframework.data.jpa.repository.query.QueryParameterSetter$NamedOrIndexedQueryParameterSetter$$Lambda$");
builder
.ignoreClass("org.springframework.amqp.")
@ -96,7 +98,10 @@ public class AdditionalLibraryIgnoredTypesConfigurer implements IgnoredTypesConf
.allowClass("org.springframework.boot.web.servlet.")
.allowClass("org.springframework.boot.autoconfigure.BackgroundPreinitializer$")
.allowClass("org.springframework.boot.autoconfigure.condition.OnClassCondition$")
.allowClass(
"org.springframework.boot.autoconfigure.web.ResourceProperties$Cache$Cachecontrol$$Lambda$")
.allowClass("org.springframework.boot.web.embedded.netty.NettyWebServer$")
.allowClass("org.springframework.boot.web.embedded.tomcat.TomcatEmbeddedContext$$Lambda$")
.allowClass(
"org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainer$")
.allowClass(
@ -127,6 +132,7 @@ public class AdditionalLibraryIgnoredTypesConfigurer implements IgnoredTypesConf
// More runnables to deal with
.allowClass("org.springframework.context.support.AbstractApplicationContext$")
.allowClass("org.springframework.context.support.ContextTypeMatchClassLoader")
.allowClass("org.springframework.context.support.DefaultLifecycleProcessor$$Lambda$")
// Allow instrumenting ApplicationContext implementations - to inject beans
.allowClass("org.springframework.context.annotation.AnnotationConfigApplicationContext")
.allowClass("org.springframework.context.support.AbstractApplicationContext")
@ -222,7 +228,8 @@ public class AdditionalLibraryIgnoredTypesConfigurer implements IgnoredTypesConf
builder
.ignoreClass("com.google.common.")
.allowClass("com.google.common.util.concurrent.")
.allowClass("com.google.common.base.internal.Finalizer");
.allowClass("com.google.common.base.internal.Finalizer")
.allowClass("com.google.common.base.Java8Usage$$Lambda$");
builder
.ignoreClass("com.google.inject.")

View File

@ -56,12 +56,7 @@ public class GlobalIgnoredTypesConfigurer implements IgnoredTypesConfigurer {
// clojure
builder.ignoreClass("clojure.").ignoreClass("$fn__");
builder
.ignoreClass("io.opentelemetry.javaagent.")
// FIXME: We should remove this once
// https://github.com/raphw/byte-buddy/issues/558 is fixed
.allowClass("io.opentelemetry.javaagent.instrumentation.api.concurrent.RunnableWrapper")
.allowClass("io.opentelemetry.javaagent.instrumentation.api.concurrent.CallableWrapper");
builder.ignoreClass("io.opentelemetry.javaagent.");
builder
.ignoreClass("java.")
@ -72,6 +67,7 @@ public class GlobalIgnoredTypesConfigurer implements IgnoredTypesConfigurer {
.allowClass("java.util.concurrent.")
.allowClass("java.lang.reflect.Proxy")
.allowClass("java.lang.ClassLoader")
.allowClass("java.lang.invoke.InnerClassLambdaMetafactory")
// Concurrent instrumentation modifies the structure of
// Cleaner class incompatibly with java9+ modules.
// Working around until a long-term fix for modules can be

View File

@ -33,7 +33,7 @@ public class IgnoredTypesMatcher extends ElementMatcher.Junction.AbstractBase<Ty
}
// bytecode proxies typically have $$ in their name
if (name.contains("$$")) {
if (name.contains("$$") && !name.contains("$$Lambda$")) {
// allow scala anonymous classes
return !name.contains("$$anon$");
}

View File

@ -66,6 +66,7 @@ dependencies {
baseJavaagentLibs(project(":instrumentation:executors:javaagent"))
baseJavaagentLibs(project(":instrumentation:internal:internal-class-loader:javaagent"))
baseJavaagentLibs(project(":instrumentation:internal:internal-eclipse-osgi-3.6:javaagent"))
baseJavaagentLibs(project(":instrumentation:internal:internal-lambda:javaagent"))
baseJavaagentLibs(project(":instrumentation:internal:internal-proxy:javaagent"))
baseJavaagentLibs(project(":instrumentation:internal:internal-reflection:javaagent"))
baseJavaagentLibs(project(":instrumentation:internal:internal-url-class-loader:javaagent"))

View File

@ -120,6 +120,7 @@ include(":instrumentation:cdi-testing")
include(":instrumentation:internal:internal-class-loader:javaagent")
include(":instrumentation:internal:internal-class-loader:javaagent-integration-tests")
include(":instrumentation:internal:internal-eclipse-osgi-3.6:javaagent")
include(":instrumentation:internal:internal-lambda:javaagent")
include(":instrumentation:internal:internal-proxy:javaagent")
include(":instrumentation:internal:internal-proxy:javaagent-unit-tests")
include(":instrumentation:internal:internal-reflection:javaagent")