Do not use arrays in InstrumentationModule (#3057)
* Do not use arrays in InstrumentationModule * add missing cast
This commit is contained in:
parent
d1b9413d88
commit
6fb3ec0501
|
@ -81,8 +81,8 @@ service provider files, but it needs to be told which ones explicitly:
|
|||
|
||||
```java
|
||||
@Override
|
||||
public String[] helperResourceNames() {
|
||||
return new String[] {"META-INF/services/org.my.library.SpiClass"};
|
||||
public List<String> helperResourceNames() {
|
||||
return singletonList("META-INF/services/org.my.library.SpiClass");
|
||||
}
|
||||
```
|
||||
|
||||
|
|
|
@ -6,13 +6,13 @@
|
|||
package io.opentelemetry.javaagent.instrumentation.apachedubbo.v2_7;
|
||||
|
||||
import static io.opentelemetry.javaagent.extension.matcher.ClassLoaderMatcher.hasClassesNamed;
|
||||
import static java.util.Collections.singletonList;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule;
|
||||
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
|
||||
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import net.bytebuddy.description.type.TypeDescription;
|
||||
import net.bytebuddy.matcher.ElementMatcher;
|
||||
|
@ -24,10 +24,8 @@ public class DubboInstrumentationModule extends InstrumentationModule {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String[] helperResourceNames() {
|
||||
return new String[] {
|
||||
"META-INF/services/org.apache.dubbo.rpc.Filter",
|
||||
};
|
||||
public List<String> helperResourceNames() {
|
||||
return singletonList("META-INF/services/org.apache.dubbo.rpc.Filter");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -37,7 +35,7 @@ public class DubboInstrumentationModule extends InstrumentationModule {
|
|||
|
||||
@Override
|
||||
public List<TypeInstrumentation> typeInstrumentations() {
|
||||
return Collections.singletonList(new ResourceInjectingTypeInstrumentation());
|
||||
return singletonList(new ResourceInjectingTypeInstrumentation());
|
||||
}
|
||||
|
||||
// A type instrumentation is needed to trigger resource injection.
|
||||
|
|
|
@ -6,13 +6,13 @@
|
|||
package io.opentelemetry.javaagent.instrumentation.awssdk.v2_2;
|
||||
|
||||
import static io.opentelemetry.javaagent.extension.matcher.ClassLoaderMatcher.hasClassesNamed;
|
||||
import static java.util.Collections.singletonList;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule;
|
||||
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
|
||||
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import net.bytebuddy.description.type.TypeDescription;
|
||||
import net.bytebuddy.matcher.ElementMatcher;
|
||||
|
@ -33,10 +33,8 @@ public class AwsSdkInstrumentationModule extends InstrumentationModule {
|
|||
* service loading mechanism to pick it up.
|
||||
*/
|
||||
@Override
|
||||
public String[] helperResourceNames() {
|
||||
return new String[] {
|
||||
"software/amazon/awssdk/global/handlers/execution.interceptors",
|
||||
};
|
||||
public List<String> helperResourceNames() {
|
||||
return singletonList("software/amazon/awssdk/global/handlers/execution.interceptors");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -48,7 +46,7 @@ public class AwsSdkInstrumentationModule extends InstrumentationModule {
|
|||
|
||||
@Override
|
||||
public List<TypeInstrumentation> typeInstrumentations() {
|
||||
return Collections.singletonList(new ResourceInjectingTypeInstrumentation());
|
||||
return singletonList(new ResourceInjectingTypeInstrumentation());
|
||||
}
|
||||
|
||||
// A type instrumentation is needed to trigger resource injection.
|
||||
|
|
|
@ -29,8 +29,8 @@ public class TestInstrumentationModule extends InstrumentationModule {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String[] helperResourceNames() {
|
||||
return new String[] {"test-resources/test-resource.txt"};
|
||||
public List<String> helperResourceNames() {
|
||||
return singletonList("test-resources/test-resource.txt");
|
||||
}
|
||||
|
||||
public static class TestTypeInstrumentation implements TypeInstrumentation {
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
package io.opentelemetry.javaagent.instrumentation.log4j.v2_13_2;
|
||||
|
||||
import static io.opentelemetry.javaagent.extension.matcher.ClassLoaderMatcher.hasClassesNamed;
|
||||
import static java.util.Collections.singletonList;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
|
@ -24,10 +25,9 @@ public class Log4j2InstrumentationModule extends InstrumentationModule {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String[] helperResourceNames() {
|
||||
return new String[] {
|
||||
"META-INF/services/org.apache.logging.log4j.core.util.ContextDataProvider",
|
||||
};
|
||||
public List<String> helperResourceNames() {
|
||||
return singletonList(
|
||||
"META-INF/services/org.apache.logging.log4j.core.util.ContextDataProvider");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -5,6 +5,9 @@
|
|||
|
||||
package io.opentelemetry.javaagent.instrumentation.methods;
|
||||
|
||||
import static java.util.Collections.emptyList;
|
||||
import static java.util.Collections.singletonList;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import io.opentelemetry.instrumentation.api.config.Config;
|
||||
import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule;
|
||||
|
@ -47,10 +50,10 @@ public class MethodInstrumentationModule extends InstrumentationModule {
|
|||
// the default configuration has empty "otel.instrumentation.methods.include", and so doesn't
|
||||
// generate any TypeInstrumentation for muzzle to analyze
|
||||
@Override
|
||||
public String[] getMuzzleHelperClassNames() {
|
||||
public List<String> getMuzzleHelperClassNames() {
|
||||
return typeInstrumentations.isEmpty()
|
||||
? new String[0]
|
||||
: new String[] {"io.opentelemetry.javaagent.instrumentation.methods.MethodTracer"};
|
||||
? emptyList()
|
||||
: singletonList("io.opentelemetry.javaagent.instrumentation.methods.MethodTracer");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -31,9 +31,6 @@ import net.bytebuddy.matcher.ElementMatcher;
|
|||
* java.util.ServiceLoader} for more details.
|
||||
*/
|
||||
public abstract class InstrumentationModule {
|
||||
private static final String[] EMPTY = new String[0];
|
||||
private static final ClassRef[] EMPTY_REFS = new ClassRef[0];
|
||||
|
||||
private static final boolean DEFAULT_ENABLED =
|
||||
Config.get().getBooleanProperty("otel.instrumentation.common.default-enabled", true);
|
||||
|
||||
|
@ -128,9 +125,9 @@ public abstract class InstrumentationModule {
|
|||
return false;
|
||||
}
|
||||
|
||||
/** Returns resource names to inject into the user's classloader. */
|
||||
public String[] helperResourceNames() {
|
||||
return EMPTY;
|
||||
/** Returns a list of resource names to inject into the user's classloader. */
|
||||
public List<String> helperResourceNames() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -152,8 +149,8 @@ public abstract class InstrumentationModule {
|
|||
public abstract List<TypeInstrumentation> typeInstrumentations();
|
||||
|
||||
/**
|
||||
* Returns a list of references to helper and library classes used in this module's type
|
||||
* instrumentation advices.
|
||||
* Returns references to helper and library classes used in this module's type instrumentation
|
||||
* advices, grouped by {@link ClassRef#getClassName()}.
|
||||
*
|
||||
* <p>The actual implementation of this method is generated automatically during compilation by
|
||||
* the {@code io.opentelemetry.javaagent.tooling.muzzle.collector.MuzzleCodeGenerationPlugin}
|
||||
|
@ -162,8 +159,8 @@ public abstract class InstrumentationModule {
|
|||
* <p><b>This method is generated automatically</b>: if you override it, the muzzle compile plugin
|
||||
* will not generate a new implementation, it will leave the existing one.
|
||||
*/
|
||||
public ClassRef[] getMuzzleReferences() {
|
||||
return EMPTY_REFS;
|
||||
public Map<String, ClassRef> getMuzzleReferences() {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -177,8 +174,8 @@ public abstract class InstrumentationModule {
|
|||
* <p><b>This method is generated automatically</b>: if you override it, the muzzle compile plugin
|
||||
* will not generate a new implementation, it will leave the existing one.
|
||||
*/
|
||||
public String[] getMuzzleHelperClassNames() {
|
||||
return EMPTY;
|
||||
public List<String> getMuzzleHelperClassNames() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
package io.opentelemetry.javaagent.tooling.instrumentation;
|
||||
|
||||
import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.failSafe;
|
||||
import static java.util.Arrays.asList;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.isAnnotatedWith;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.not;
|
||||
|
@ -49,8 +48,8 @@ public final class InstrumentationModuleInstaller {
|
|||
log.debug("Instrumentation {} is disabled", instrumentationModule.instrumentationName());
|
||||
return parentAgentBuilder;
|
||||
}
|
||||
List<String> helperClassNames = asList(instrumentationModule.getMuzzleHelperClassNames());
|
||||
List<String> helperResourceNames = asList(instrumentationModule.helperResourceNames());
|
||||
List<String> helperClassNames = instrumentationModule.getMuzzleHelperClassNames();
|
||||
List<String> helperResourceNames = instrumentationModule.helperResourceNames();
|
||||
List<TypeInstrumentation> typeInstrumentations = instrumentationModule.typeInstrumentations();
|
||||
if (typeInstrumentations.isEmpty()) {
|
||||
if (!helperClassNames.isEmpty() || !helperResourceNames.isEmpty()) {
|
||||
|
|
|
@ -14,11 +14,12 @@ import io.opentelemetry.javaagent.extension.muzzle.Flag;
|
|||
import io.opentelemetry.javaagent.extension.muzzle.MethodRef;
|
||||
import io.opentelemetry.javaagent.extension.muzzle.Source;
|
||||
import io.opentelemetry.javaagent.tooling.Utils;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import net.bytebuddy.ClassFileVersion;
|
||||
import net.bytebuddy.asm.AsmVisitorWrapper;
|
||||
import net.bytebuddy.description.field.FieldDescription;
|
||||
import net.bytebuddy.description.field.FieldList;
|
||||
|
@ -27,8 +28,6 @@ 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.FieldVisitor;
|
||||
import net.bytebuddy.jar.asm.Label;
|
||||
import net.bytebuddy.jar.asm.MethodVisitor;
|
||||
import net.bytebuddy.jar.asm.Opcodes;
|
||||
import net.bytebuddy.jar.asm.Type;
|
||||
|
@ -47,7 +46,6 @@ import org.slf4j.LoggerFactory;
|
|||
class MuzzleCodeGenerator implements AsmVisitorWrapper {
|
||||
private static final Logger log = LoggerFactory.getLogger(MuzzleCodeGenerator.class);
|
||||
|
||||
private static final String MUZZLE_REFERENCES_FIELD_NAME = "muzzleReferences";
|
||||
private static final String MUZZLE_REFERENCES_METHOD_NAME = "getMuzzleReferences";
|
||||
private static final String MUZZLE_HELPER_CLASSES_METHOD_NAME = "getMuzzleHelperClassNames";
|
||||
private static final String MUZZLE_CONTEXT_STORE_CLASSES_METHOD_NAME =
|
||||
|
@ -73,26 +71,20 @@ class MuzzleCodeGenerator implements AsmVisitorWrapper {
|
|||
MethodList<?> methods,
|
||||
int writerFlags,
|
||||
int readerFlags) {
|
||||
return new GenerateMuzzleMethodsAndFields(
|
||||
classVisitor,
|
||||
implementationContext.getClassFileVersion().isAtLeast(ClassFileVersion.JAVA_V6));
|
||||
return new GenerateMuzzleMethodsAndFields(classVisitor);
|
||||
}
|
||||
|
||||
private static class GenerateMuzzleMethodsAndFields extends ClassVisitor {
|
||||
|
||||
private final boolean frames;
|
||||
|
||||
private String instrumentationClassName;
|
||||
private InstrumentationModule instrumentationModule;
|
||||
|
||||
private boolean generateReferencesField = true;
|
||||
private boolean generateReferencesMethod = true;
|
||||
private boolean generateHelperClassNamesMethod = true;
|
||||
private boolean generateContextStoreClassesMethod = true;
|
||||
|
||||
public GenerateMuzzleMethodsAndFields(ClassVisitor classVisitor, boolean frames) {
|
||||
public GenerateMuzzleMethodsAndFields(ClassVisitor classVisitor) {
|
||||
super(Opcodes.ASM7, classVisitor);
|
||||
this.frames = frames;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -118,19 +110,6 @@ class MuzzleCodeGenerator implements AsmVisitorWrapper {
|
|||
super.visit(version, access, name, signature, superName, interfaces);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FieldVisitor visitField(
|
||||
int access, String name, String descriptor, String signature, Object value) {
|
||||
if (MUZZLE_REFERENCES_FIELD_NAME.equals(name)) {
|
||||
generateReferencesField = false;
|
||||
log.info(
|
||||
"The '{}' field was already found in class '{}'. Muzzle will not generate it again",
|
||||
MUZZLE_REFERENCES_FIELD_NAME,
|
||||
instrumentationClassName);
|
||||
}
|
||||
return super.visitField(access, name, descriptor, signature, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodVisitor visitMethod(
|
||||
int access, String name, String descriptor, String signature, String[] exceptions) {
|
||||
|
@ -155,20 +134,12 @@ class MuzzleCodeGenerator implements AsmVisitorWrapper {
|
|||
MUZZLE_CONTEXT_STORE_CLASSES_METHOD_NAME,
|
||||
instrumentationClassName);
|
||||
}
|
||||
MethodVisitor methodVisitor =
|
||||
super.visitMethod(access, name, descriptor, signature, exceptions);
|
||||
if ("<init>".equals(name)) {
|
||||
methodVisitor = new InitializeReferencesField(methodVisitor);
|
||||
}
|
||||
return methodVisitor;
|
||||
return super.visitMethod(access, name, descriptor, signature, exceptions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitEnd() {
|
||||
ReferenceCollector collector = collectReferences();
|
||||
if (generateReferencesField) {
|
||||
generateMuzzleReferencesField();
|
||||
}
|
||||
if (generateReferencesMethod) {
|
||||
generateMuzzleReferencesMethod(collector);
|
||||
}
|
||||
|
@ -198,353 +169,323 @@ class MuzzleCodeGenerator implements AsmVisitorWrapper {
|
|||
return collector;
|
||||
}
|
||||
|
||||
private void generateMuzzleReferencesMethod(ReferenceCollector collector) {
|
||||
Type referenceType = Type.getType(ClassRef.class);
|
||||
Type referenceBuilderType = Type.getType(ClassRefBuilder.class);
|
||||
Type referenceFlagType = Type.getType(Flag.class);
|
||||
Type referenceFlagArrayType = Type.getType(Flag[].class);
|
||||
Type referenceSourceArrayType = Type.getType(Source[].class);
|
||||
Type stringType = Type.getType(String.class);
|
||||
Type typeType = Type.getType(Type.class);
|
||||
Type typeArrayType = Type.getType(Type[].class);
|
||||
|
||||
/*
|
||||
* public Map<String, ClassRef> getMuzzleReferences() {
|
||||
* Map<String, ClassRef> references = new HashMap<>(...);
|
||||
* references.put("reference class name", ClassRef.newBuilder(...)
|
||||
* ...
|
||||
* .build());
|
||||
* return references;
|
||||
* }
|
||||
*/
|
||||
MethodVisitor mv =
|
||||
super.visitMethod(
|
||||
Opcodes.ACC_PUBLIC, MUZZLE_REFERENCES_METHOD_NAME, "()Ljava/util/Map;", null, null);
|
||||
mv.visitCode();
|
||||
|
||||
Collection<ClassRef> references = collector.getReferences().values();
|
||||
|
||||
writeNewMap(mv, references.size());
|
||||
// stack: map
|
||||
mv.visitVarInsn(Opcodes.ASTORE, 1);
|
||||
// stack: <empty>
|
||||
|
||||
references.forEach(
|
||||
reference -> {
|
||||
mv.visitVarInsn(Opcodes.ALOAD, 1);
|
||||
// stack: map
|
||||
mv.visitLdcInsn(reference.getClassName());
|
||||
// stack: map, className
|
||||
|
||||
mv.visitLdcInsn(reference.getClassName());
|
||||
mv.visitMethodInsn(
|
||||
Opcodes.INVOKESTATIC,
|
||||
referenceType.getInternalName(),
|
||||
"newBuilder",
|
||||
Type.getMethodDescriptor(referenceBuilderType, stringType),
|
||||
false);
|
||||
// stack: map, className, builder
|
||||
|
||||
for (Source source : reference.getSources()) {
|
||||
mv.visitLdcInsn(source.getName());
|
||||
mv.visitLdcInsn(source.getLine());
|
||||
mv.visitMethodInsn(
|
||||
Opcodes.INVOKEVIRTUAL,
|
||||
referenceBuilderType.getInternalName(),
|
||||
"addSource",
|
||||
Type.getMethodDescriptor(referenceBuilderType, stringType, Type.INT_TYPE),
|
||||
false);
|
||||
}
|
||||
// stack: map, className, builder
|
||||
for (Flag flag : reference.getFlags()) {
|
||||
String enumClassName = getEnumClassInternalName(flag);
|
||||
mv.visitFieldInsn(
|
||||
Opcodes.GETSTATIC, enumClassName, flag.name(), "L" + enumClassName + ";");
|
||||
mv.visitMethodInsn(
|
||||
Opcodes.INVOKEVIRTUAL,
|
||||
referenceBuilderType.getInternalName(),
|
||||
"addFlag",
|
||||
Type.getMethodDescriptor(referenceBuilderType, referenceFlagType),
|
||||
false);
|
||||
}
|
||||
// stack: map, className, builder
|
||||
if (null != reference.getSuperClassName()) {
|
||||
mv.visitLdcInsn(reference.getSuperClassName());
|
||||
mv.visitMethodInsn(
|
||||
Opcodes.INVOKEVIRTUAL,
|
||||
referenceBuilderType.getInternalName(),
|
||||
"setSuperClassName",
|
||||
Type.getMethodDescriptor(referenceBuilderType, stringType),
|
||||
false);
|
||||
}
|
||||
// stack: map, className, builder
|
||||
for (String interfaceName : reference.getInterfaceNames()) {
|
||||
mv.visitLdcInsn(interfaceName);
|
||||
mv.visitMethodInsn(
|
||||
Opcodes.INVOKEVIRTUAL,
|
||||
referenceBuilderType.getInternalName(),
|
||||
"addInterfaceName",
|
||||
Type.getMethodDescriptor(referenceBuilderType, stringType),
|
||||
false);
|
||||
}
|
||||
// stack: map, className, builder
|
||||
for (FieldRef field : reference.getFields()) {
|
||||
writeSourcesArray(mv, field.getSources());
|
||||
writeFlagsArray(mv, field.getFlags());
|
||||
// field name
|
||||
mv.visitLdcInsn(field.getName());
|
||||
writeType(mv, field.getDescriptor());
|
||||
// declared flag
|
||||
mv.visitLdcInsn(field.isDeclared());
|
||||
|
||||
mv.visitMethodInsn(
|
||||
Opcodes.INVOKEVIRTUAL,
|
||||
referenceBuilderType.getInternalName(),
|
||||
"addField",
|
||||
Type.getMethodDescriptor(
|
||||
referenceBuilderType,
|
||||
referenceSourceArrayType,
|
||||
referenceFlagArrayType,
|
||||
stringType,
|
||||
typeType,
|
||||
Type.BOOLEAN_TYPE),
|
||||
false);
|
||||
}
|
||||
// stack: map, className, builder
|
||||
for (MethodRef method : reference.getMethods()) {
|
||||
writeSourcesArray(mv, method.getSources());
|
||||
writeFlagsArray(mv, method.getFlags());
|
||||
// method name
|
||||
mv.visitLdcInsn(method.getName());
|
||||
// method return and argument types
|
||||
{
|
||||
// we cannot pass the whole method descriptor string as it won't be shaded, so
|
||||
// we
|
||||
// have to pass the return and parameter types separately - strings in
|
||||
// Type.getType()
|
||||
// calls will be shaded correctly
|
||||
Type methodType = Type.getMethodType(method.getDescriptor());
|
||||
|
||||
writeType(mv, methodType.getReturnType().getDescriptor());
|
||||
|
||||
mv.visitLdcInsn(methodType.getArgumentTypes().length);
|
||||
mv.visitTypeInsn(Opcodes.ANEWARRAY, typeType.getInternalName());
|
||||
int i = 0;
|
||||
for (Type parameterType : methodType.getArgumentTypes()) {
|
||||
mv.visitInsn(Opcodes.DUP);
|
||||
mv.visitLdcInsn(i);
|
||||
writeType(mv, parameterType.getDescriptor());
|
||||
mv.visitInsn(Opcodes.AASTORE);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
mv.visitMethodInsn(
|
||||
Opcodes.INVOKEVIRTUAL,
|
||||
referenceBuilderType.getInternalName(),
|
||||
"addMethod",
|
||||
Type.getMethodDescriptor(
|
||||
referenceBuilderType,
|
||||
referenceSourceArrayType,
|
||||
referenceFlagArrayType,
|
||||
stringType,
|
||||
typeType,
|
||||
typeArrayType),
|
||||
false);
|
||||
}
|
||||
// stack: map, className, builder
|
||||
mv.visitMethodInsn(
|
||||
Opcodes.INVOKEVIRTUAL,
|
||||
referenceBuilderType.getInternalName(),
|
||||
"build",
|
||||
Type.getMethodDescriptor(referenceType),
|
||||
false);
|
||||
// stack: map, className, classRef
|
||||
|
||||
mv.visitMethodInsn(
|
||||
Opcodes.INVOKEINTERFACE,
|
||||
"java/util/Map",
|
||||
"put",
|
||||
"(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
|
||||
true);
|
||||
// stack: previousValue
|
||||
mv.visitInsn(Opcodes.POP);
|
||||
// stack: <empty>
|
||||
});
|
||||
|
||||
mv.visitVarInsn(Opcodes.ALOAD, 1);
|
||||
// stack: map
|
||||
mv.visitInsn(Opcodes.ARETURN);
|
||||
|
||||
mv.visitMaxs(0, 0); // recomputed
|
||||
mv.visitEnd();
|
||||
}
|
||||
|
||||
private void writeNewMap(MethodVisitor mv, int size) {
|
||||
mv.visitTypeInsn(Opcodes.NEW, "java/util/HashMap");
|
||||
// stack: map
|
||||
mv.visitInsn(Opcodes.DUP);
|
||||
// stack: map, map
|
||||
// pass bigger size to avoid resizes; same formula as in e.g. HashSet(Collection)
|
||||
// 0.75 is the default load factor
|
||||
mv.visitLdcInsn((int) (size / 0.75f) + 1);
|
||||
// stack: map, map, size
|
||||
mv.visitLdcInsn(0.75f);
|
||||
// stack: map, map, size, loadFactor
|
||||
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/util/HashMap", "<init>", "(IF)V", false);
|
||||
}
|
||||
|
||||
private void writeSourcesArray(MethodVisitor mv, Set<Source> sources) {
|
||||
Type referenceSourceType = Type.getType(Source.class);
|
||||
|
||||
mv.visitLdcInsn(sources.size());
|
||||
mv.visitTypeInsn(Opcodes.ANEWARRAY, referenceSourceType.getInternalName());
|
||||
|
||||
int i = 0;
|
||||
for (Source source : sources) {
|
||||
mv.visitInsn(Opcodes.DUP);
|
||||
mv.visitLdcInsn(i);
|
||||
|
||||
mv.visitTypeInsn(Opcodes.NEW, referenceSourceType.getInternalName());
|
||||
mv.visitInsn(Opcodes.DUP);
|
||||
mv.visitLdcInsn(source.getName());
|
||||
mv.visitLdcInsn(source.getLine());
|
||||
mv.visitMethodInsn(
|
||||
Opcodes.INVOKESPECIAL,
|
||||
referenceSourceType.getInternalName(),
|
||||
"<init>",
|
||||
"(Ljava/lang/String;I)V",
|
||||
false);
|
||||
|
||||
mv.visitInsn(Opcodes.AASTORE);
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
private void writeFlagsArray(MethodVisitor mv, Set<Flag> flags) {
|
||||
Type referenceFlagType = Type.getType(Flag.class);
|
||||
|
||||
mv.visitLdcInsn(flags.size());
|
||||
mv.visitTypeInsn(Opcodes.ANEWARRAY, referenceFlagType.getInternalName());
|
||||
|
||||
int i = 0;
|
||||
for (Flag flag : flags) {
|
||||
mv.visitInsn(Opcodes.DUP);
|
||||
mv.visitLdcInsn(i);
|
||||
String enumClassName = getEnumClassInternalName(flag);
|
||||
mv.visitFieldInsn(Opcodes.GETSTATIC, enumClassName, flag.name(), "L" + enumClassName + ";");
|
||||
mv.visitInsn(Opcodes.AASTORE);
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
private static final Pattern ANONYMOUS_ENUM_CONSTANT_CLASS =
|
||||
Pattern.compile("(?<enumClass>.*)\\$[0-9]+$");
|
||||
|
||||
// drops "$1" suffix for enum constants that override/implement super class methods
|
||||
private String getEnumClassInternalName(Flag flag) {
|
||||
String fullInternalName = Utils.getInternalName(flag.getClass());
|
||||
Matcher m = ANONYMOUS_ENUM_CONSTANT_CLASS.matcher(fullInternalName);
|
||||
return m.matches() ? m.group("enumClass") : fullInternalName;
|
||||
}
|
||||
|
||||
private void writeType(MethodVisitor mv, String descriptor) {
|
||||
Type typeType = Type.getType(Type.class);
|
||||
|
||||
mv.visitLdcInsn(descriptor);
|
||||
mv.visitMethodInsn(
|
||||
Opcodes.INVOKESTATIC,
|
||||
typeType.getInternalName(),
|
||||
"getType",
|
||||
Type.getMethodDescriptor(typeType, Type.getType(String.class)),
|
||||
false);
|
||||
}
|
||||
|
||||
private void generateMuzzleHelperClassNamesMethod(ReferenceCollector collector) {
|
||||
/*
|
||||
* public String[] getMuzzleHelperClassNames() {
|
||||
* return new String[] {
|
||||
* // sorted helper class names
|
||||
* };
|
||||
* public List<String> getMuzzleHelperClassNames() {
|
||||
* List<String> helperClassNames = new ArrayList<>(...);
|
||||
* helperClassNames.add(...);
|
||||
* return helperClassNames;
|
||||
* }
|
||||
*/
|
||||
MethodVisitor mv =
|
||||
super.visitMethod(
|
||||
Opcodes.ACC_PUBLIC,
|
||||
MUZZLE_HELPER_CLASSES_METHOD_NAME,
|
||||
"()[Ljava/lang/String;",
|
||||
"()Ljava/util/List;",
|
||||
null,
|
||||
null);
|
||||
mv.visitCode();
|
||||
|
||||
List<String> helperClassNames = collector.getSortedHelperClasses();
|
||||
|
||||
mv.visitTypeInsn(Opcodes.NEW, "java/util/ArrayList");
|
||||
// stack: list
|
||||
mv.visitInsn(Opcodes.DUP);
|
||||
// stack: list, list
|
||||
mv.visitLdcInsn(helperClassNames.size());
|
||||
// stack: size
|
||||
mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/String");
|
||||
// stack: array
|
||||
for (int i = 0; i < helperClassNames.size(); ++i) {
|
||||
String helperClassName = helperClassNames.get(i);
|
||||
// stack: list, list, size
|
||||
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/util/ArrayList", "<init>", "(I)V", false);
|
||||
// stack: list
|
||||
mv.visitVarInsn(Opcodes.ASTORE, 1);
|
||||
// stack: <empty>
|
||||
|
||||
mv.visitInsn(Opcodes.DUP);
|
||||
// stack: array, array
|
||||
mv.visitLdcInsn(i);
|
||||
// stack: array, array, i
|
||||
mv.visitLdcInsn(helperClassName);
|
||||
// stack: array, array, i, helperClassName
|
||||
mv.visitInsn(Opcodes.AASTORE);
|
||||
// stack: array
|
||||
}
|
||||
helperClassNames.forEach(
|
||||
helperClassName -> {
|
||||
mv.visitVarInsn(Opcodes.ALOAD, 1);
|
||||
// stack: list
|
||||
mv.visitLdcInsn(helperClassName);
|
||||
// stack: list, helperClassName
|
||||
mv.visitMethodInsn(
|
||||
Opcodes.INVOKEINTERFACE, "java/util/List", "add", "(Ljava/lang/Object;)Z", true);
|
||||
// stack: added
|
||||
mv.visitInsn(Opcodes.POP);
|
||||
// stack: <empty>
|
||||
});
|
||||
|
||||
mv.visitVarInsn(Opcodes.ALOAD, 1);
|
||||
// stack: list
|
||||
mv.visitInsn(Opcodes.ARETURN);
|
||||
|
||||
mv.visitMaxs(0, 0);
|
||||
mv.visitEnd();
|
||||
}
|
||||
|
||||
private void generateMuzzleReferencesMethod(ReferenceCollector collector) {
|
||||
Type referenceType = Type.getType(ClassRef.class);
|
||||
Type referenceArrayType = Type.getType(ClassRef[].class);
|
||||
Type referenceBuilderType = Type.getType(ClassRefBuilder.class);
|
||||
Type referenceFlagType = Type.getType(Flag.class);
|
||||
Type referenceSourceType = Type.getType(Source.class);
|
||||
Type stringType = Type.getType(String.class);
|
||||
Type typeType = Type.getType(Type.class);
|
||||
|
||||
/*
|
||||
* public synchronized Reference[] getMuzzleReferences() {
|
||||
* if (null == this.muzzleReferences) {
|
||||
* this.muzzleReferences = new Reference[] {
|
||||
* // reference builders
|
||||
* };
|
||||
* }
|
||||
* return this.muzzleReferences;
|
||||
* }
|
||||
*/
|
||||
try {
|
||||
MethodVisitor mv =
|
||||
super.visitMethod(
|
||||
Opcodes.ACC_PUBLIC + Opcodes.ACC_SYNCHRONIZED,
|
||||
MUZZLE_REFERENCES_METHOD_NAME,
|
||||
Type.getMethodDescriptor(referenceArrayType),
|
||||
null,
|
||||
null);
|
||||
|
||||
mv.visitCode();
|
||||
Label start = new Label();
|
||||
Label ret = new Label();
|
||||
Label finish = new Label();
|
||||
|
||||
mv.visitLabel(start);
|
||||
mv.visitInsn(Opcodes.ACONST_NULL);
|
||||
mv.visitVarInsn(Opcodes.ALOAD, 0);
|
||||
mv.visitFieldInsn(
|
||||
Opcodes.GETFIELD,
|
||||
instrumentationClassName,
|
||||
MUZZLE_REFERENCES_FIELD_NAME,
|
||||
referenceArrayType.getDescriptor());
|
||||
mv.visitJumpInsn(Opcodes.IF_ACMPNE, ret);
|
||||
|
||||
mv.visitVarInsn(Opcodes.ALOAD, 0);
|
||||
|
||||
ClassRef[] references = collector.getReferences().values().toArray(new ClassRef[0]);
|
||||
mv.visitLdcInsn(references.length);
|
||||
mv.visitTypeInsn(Opcodes.ANEWARRAY, referenceType.getInternalName());
|
||||
|
||||
for (int i = 0; i < references.length; ++i) {
|
||||
mv.visitInsn(Opcodes.DUP);
|
||||
mv.visitLdcInsn(i);
|
||||
mv.visitLdcInsn(references[i].getClassName());
|
||||
mv.visitMethodInsn(
|
||||
Opcodes.INVOKESTATIC,
|
||||
referenceType.getInternalName(),
|
||||
"newBuilder",
|
||||
Type.getMethodDescriptor(referenceBuilderType, stringType),
|
||||
false);
|
||||
|
||||
for (Source source : references[i].getSources()) {
|
||||
mv.visitLdcInsn(source.getName());
|
||||
mv.visitLdcInsn(source.getLine());
|
||||
mv.visitMethodInsn(
|
||||
Opcodes.INVOKEVIRTUAL,
|
||||
referenceBuilderType.getInternalName(),
|
||||
"addSource",
|
||||
Type.getMethodDescriptor(referenceBuilderType, stringType, Type.INT_TYPE),
|
||||
false);
|
||||
}
|
||||
for (Flag flag : references[i].getFlags()) {
|
||||
String enumClassName = getEnumClassInternalName(flag);
|
||||
mv.visitFieldInsn(
|
||||
Opcodes.GETSTATIC, enumClassName, flag.name(), "L" + enumClassName + ";");
|
||||
mv.visitMethodInsn(
|
||||
Opcodes.INVOKEVIRTUAL,
|
||||
referenceBuilderType.getInternalName(),
|
||||
"addFlag",
|
||||
Type.getMethodDescriptor(referenceBuilderType, referenceFlagType),
|
||||
false);
|
||||
}
|
||||
if (null != references[i].getSuperClassName()) {
|
||||
mv.visitLdcInsn(references[i].getSuperClassName());
|
||||
mv.visitMethodInsn(
|
||||
Opcodes.INVOKEVIRTUAL,
|
||||
referenceBuilderType.getInternalName(),
|
||||
"setSuperClassName",
|
||||
Type.getMethodDescriptor(referenceBuilderType, stringType),
|
||||
false);
|
||||
}
|
||||
for (String interfaceName : references[i].getInterfaceNames()) {
|
||||
mv.visitLdcInsn(interfaceName);
|
||||
mv.visitMethodInsn(
|
||||
Opcodes.INVOKEVIRTUAL,
|
||||
referenceBuilderType.getInternalName(),
|
||||
"addInterfaceName",
|
||||
Type.getMethodDescriptor(referenceBuilderType, stringType),
|
||||
false);
|
||||
}
|
||||
for (FieldRef field : references[i].getFields()) {
|
||||
{ // sources
|
||||
mv.visitLdcInsn(field.getSources().size());
|
||||
mv.visitTypeInsn(Opcodes.ANEWARRAY, referenceSourceType.getInternalName());
|
||||
|
||||
int j = 0;
|
||||
for (Source source : field.getSources()) {
|
||||
mv.visitInsn(Opcodes.DUP);
|
||||
mv.visitLdcInsn(j);
|
||||
|
||||
mv.visitTypeInsn(Opcodes.NEW, referenceSourceType.getInternalName());
|
||||
mv.visitInsn(Opcodes.DUP);
|
||||
mv.visitLdcInsn(source.getName());
|
||||
mv.visitLdcInsn(source.getLine());
|
||||
mv.visitMethodInsn(
|
||||
Opcodes.INVOKESPECIAL,
|
||||
referenceSourceType.getInternalName(),
|
||||
"<init>",
|
||||
"(Ljava/lang/String;I)V",
|
||||
false);
|
||||
|
||||
mv.visitInsn(Opcodes.AASTORE);
|
||||
++j;
|
||||
}
|
||||
}
|
||||
|
||||
{ // flags
|
||||
mv.visitLdcInsn(field.getFlags().size());
|
||||
mv.visitTypeInsn(Opcodes.ANEWARRAY, referenceFlagType.getInternalName());
|
||||
|
||||
int j = 0;
|
||||
for (Flag flag : field.getFlags()) {
|
||||
mv.visitInsn(Opcodes.DUP);
|
||||
mv.visitLdcInsn(j);
|
||||
String enumClassName = getEnumClassInternalName(flag);
|
||||
mv.visitFieldInsn(
|
||||
Opcodes.GETSTATIC, enumClassName, flag.name(), "L" + enumClassName + ";");
|
||||
mv.visitInsn(Opcodes.AASTORE);
|
||||
++j;
|
||||
}
|
||||
}
|
||||
|
||||
mv.visitLdcInsn(field.getName());
|
||||
|
||||
{ // field type
|
||||
mv.visitLdcInsn(field.getDescriptor());
|
||||
mv.visitMethodInsn(
|
||||
Opcodes.INVOKESTATIC,
|
||||
typeType.getInternalName(),
|
||||
"getType",
|
||||
Type.getMethodDescriptor(typeType, stringType),
|
||||
false);
|
||||
}
|
||||
|
||||
// declared flag
|
||||
mv.visitLdcInsn(field.isDeclared());
|
||||
|
||||
mv.visitMethodInsn(
|
||||
Opcodes.INVOKEVIRTUAL,
|
||||
referenceBuilderType.getInternalName(),
|
||||
"addField",
|
||||
Type.getMethodDescriptor(
|
||||
ClassRefBuilder.class.getMethod(
|
||||
"addField",
|
||||
Source[].class,
|
||||
Flag[].class,
|
||||
String.class,
|
||||
Type.class,
|
||||
boolean.class)),
|
||||
false);
|
||||
}
|
||||
for (MethodRef method : references[i].getMethods()) {
|
||||
mv.visitLdcInsn(method.getSources().size());
|
||||
mv.visitTypeInsn(Opcodes.ANEWARRAY, referenceSourceType.getInternalName());
|
||||
int j = 0;
|
||||
for (Source source : method.getSources()) {
|
||||
mv.visitInsn(Opcodes.DUP);
|
||||
mv.visitLdcInsn(j);
|
||||
|
||||
mv.visitTypeInsn(Opcodes.NEW, referenceSourceType.getInternalName());
|
||||
mv.visitInsn(Opcodes.DUP);
|
||||
mv.visitLdcInsn(source.getName());
|
||||
mv.visitLdcInsn(source.getLine());
|
||||
mv.visitMethodInsn(
|
||||
Opcodes.INVOKESPECIAL,
|
||||
referenceSourceType.getInternalName(),
|
||||
"<init>",
|
||||
"(Ljava/lang/String;I)V",
|
||||
false);
|
||||
|
||||
mv.visitInsn(Opcodes.AASTORE);
|
||||
++j;
|
||||
}
|
||||
|
||||
mv.visitLdcInsn(method.getFlags().size());
|
||||
mv.visitTypeInsn(Opcodes.ANEWARRAY, referenceFlagType.getInternalName());
|
||||
j = 0;
|
||||
for (Flag flag : method.getFlags()) {
|
||||
mv.visitInsn(Opcodes.DUP);
|
||||
mv.visitLdcInsn(j);
|
||||
String enumClassName = getEnumClassInternalName(flag);
|
||||
mv.visitFieldInsn(
|
||||
Opcodes.GETSTATIC, enumClassName, flag.name(), "L" + enumClassName + ";");
|
||||
mv.visitInsn(Opcodes.AASTORE);
|
||||
++j;
|
||||
}
|
||||
|
||||
mv.visitLdcInsn(method.getName());
|
||||
|
||||
{
|
||||
// we cannot pass the whole method descriptor string as it won't be shaded, so we
|
||||
// have to pass the return and parameter types separately - strings in Type.getType()
|
||||
// calls will be shaded correctly
|
||||
Type methodType = Type.getMethodType(method.getDescriptor());
|
||||
|
||||
// return type
|
||||
mv.visitLdcInsn(methodType.getReturnType().getDescriptor());
|
||||
mv.visitMethodInsn(
|
||||
Opcodes.INVOKESTATIC,
|
||||
typeType.getInternalName(),
|
||||
"getType",
|
||||
Type.getMethodDescriptor(typeType, stringType),
|
||||
false);
|
||||
|
||||
mv.visitLdcInsn(methodType.getArgumentTypes().length);
|
||||
mv.visitTypeInsn(Opcodes.ANEWARRAY, typeType.getInternalName());
|
||||
j = 0;
|
||||
for (Type parameterType : methodType.getArgumentTypes()) {
|
||||
mv.visitInsn(Opcodes.DUP);
|
||||
mv.visitLdcInsn(j);
|
||||
|
||||
mv.visitLdcInsn(parameterType.getDescriptor());
|
||||
mv.visitMethodInsn(
|
||||
Opcodes.INVOKESTATIC,
|
||||
typeType.getInternalName(),
|
||||
"getType",
|
||||
Type.getMethodDescriptor(typeType, stringType),
|
||||
false);
|
||||
|
||||
mv.visitInsn(Opcodes.AASTORE);
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
||||
mv.visitMethodInsn(
|
||||
Opcodes.INVOKEVIRTUAL,
|
||||
referenceBuilderType.getInternalName(),
|
||||
"addMethod",
|
||||
Type.getMethodDescriptor(
|
||||
ClassRefBuilder.class.getMethod(
|
||||
"addMethod",
|
||||
Source[].class,
|
||||
Flag[].class,
|
||||
String.class,
|
||||
Type.class,
|
||||
Type[].class)),
|
||||
false);
|
||||
}
|
||||
mv.visitMethodInsn(
|
||||
Opcodes.INVOKEVIRTUAL,
|
||||
referenceBuilderType.getInternalName(),
|
||||
"build",
|
||||
Type.getMethodDescriptor(referenceType),
|
||||
false);
|
||||
mv.visitInsn(Opcodes.AASTORE);
|
||||
}
|
||||
|
||||
mv.visitFieldInsn(
|
||||
Opcodes.PUTFIELD,
|
||||
instrumentationClassName,
|
||||
MUZZLE_REFERENCES_FIELD_NAME,
|
||||
referenceArrayType.getDescriptor());
|
||||
|
||||
mv.visitLabel(ret);
|
||||
if (frames) {
|
||||
mv.visitFrame(Opcodes.F_SAME, 1, null, 0, null);
|
||||
}
|
||||
mv.visitVarInsn(Opcodes.ALOAD, 0);
|
||||
mv.visitFieldInsn(
|
||||
Opcodes.GETFIELD,
|
||||
instrumentationClassName,
|
||||
MUZZLE_REFERENCES_FIELD_NAME,
|
||||
referenceArrayType.getDescriptor());
|
||||
mv.visitInsn(Opcodes.ARETURN);
|
||||
mv.visitLabel(finish);
|
||||
|
||||
mv.visitLocalVariable("this", "L" + instrumentationClassName + ";", null, start, finish, 0);
|
||||
mv.visitMaxs(0, 0); // recomputed
|
||||
mv.visitEnd();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void generateMuzzleReferencesField() {
|
||||
super.visitField(
|
||||
Opcodes.ACC_PRIVATE + Opcodes.ACC_VOLATILE,
|
||||
MUZZLE_REFERENCES_FIELD_NAME,
|
||||
Type.getDescriptor(ClassRef[].class),
|
||||
null,
|
||||
null);
|
||||
}
|
||||
|
||||
private void generateMuzzleContextStoreClassesMethod(ReferenceCollector collector) {
|
||||
/*
|
||||
* public Map<String, String> getMuzzleContextStoreClasses() {
|
||||
* Map<String, String> contextStore = new HashMap();
|
||||
* Map<String, String> contextStore = new HashMap<>(...);
|
||||
* contextStore.put(..., ...);
|
||||
* return contextStore;
|
||||
* }
|
||||
|
@ -560,13 +501,7 @@ class MuzzleCodeGenerator implements AsmVisitorWrapper {
|
|||
|
||||
Map<String, String> contextStoreClasses = collector.getContextStoreClasses();
|
||||
|
||||
mv.visitTypeInsn(Opcodes.NEW, "java/util/HashMap");
|
||||
// stack: map
|
||||
mv.visitInsn(Opcodes.DUP);
|
||||
// stack: map, map
|
||||
mv.visitLdcInsn(contextStoreClasses.size());
|
||||
// stack: map, map, size
|
||||
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/util/HashMap", "<init>", "(I)V", false);
|
||||
writeNewMap(mv, contextStoreClasses.size());
|
||||
// stack: map
|
||||
mv.visitVarInsn(Opcodes.ASTORE, 1);
|
||||
// stack: <empty>
|
||||
|
@ -597,36 +532,5 @@ class MuzzleCodeGenerator implements AsmVisitorWrapper {
|
|||
mv.visitMaxs(0, 0);
|
||||
mv.visitEnd();
|
||||
}
|
||||
|
||||
private static final Pattern ANONYMOUS_ENUM_CONSTANT_CLASS =
|
||||
Pattern.compile("(?<enumClass>.*)\\$[0-9]+$");
|
||||
|
||||
// drops "$1" suffix for enum constants that override/implement super class methods
|
||||
private String getEnumClassInternalName(Flag flag) {
|
||||
String fullInternalName = Utils.getInternalName(flag.getClass());
|
||||
Matcher m = ANONYMOUS_ENUM_CONSTANT_CLASS.matcher(fullInternalName);
|
||||
return m.matches() ? m.group("enumClass") : fullInternalName;
|
||||
}
|
||||
|
||||
/** Appends the {@code Reference[]} field initialization at the end of a method/constructor. */
|
||||
private class InitializeReferencesField extends MethodVisitor {
|
||||
public InitializeReferencesField(MethodVisitor methodVisitor) {
|
||||
super(Opcodes.ASM7, methodVisitor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitInsn(int opcode) {
|
||||
if (opcode == Opcodes.RETURN) {
|
||||
super.visitVarInsn(Opcodes.ALOAD, 0);
|
||||
super.visitInsn(Opcodes.ACONST_NULL);
|
||||
super.visitFieldInsn(
|
||||
Opcodes.PUTFIELD,
|
||||
instrumentationClassName,
|
||||
MUZZLE_REFERENCES_FIELD_NAME,
|
||||
Type.getDescriptor(ClassRef[].class));
|
||||
}
|
||||
super.visitInsn(opcode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
package io.opentelemetry.javaagent.tooling.muzzle.matcher;
|
||||
|
||||
import static java.lang.System.lineSeparator;
|
||||
import static java.util.Arrays.asList;
|
||||
|
||||
import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule;
|
||||
import io.opentelemetry.javaagent.extension.muzzle.ClassRef;
|
||||
|
@ -56,7 +55,7 @@ public final class MuzzleGradlePluginUtil {
|
|||
ServiceLoader.load(InstrumentationModule.class, agentClassLoader)) {
|
||||
ReferenceMatcher muzzle =
|
||||
new ReferenceMatcher(
|
||||
asList(instrumentationModule.getMuzzleHelperClassNames()),
|
||||
instrumentationModule.getMuzzleHelperClassNames(),
|
||||
instrumentationModule.getMuzzleReferences(),
|
||||
instrumentationModule::isHelperClass);
|
||||
List<Mismatch> mismatches = muzzle.getMismatchedReferenceSources(userClassLoader);
|
||||
|
@ -95,7 +94,7 @@ public final class MuzzleGradlePluginUtil {
|
|||
ServiceLoader.load(InstrumentationModule.class, agentClassLoader)) {
|
||||
try {
|
||||
// verify helper injector works
|
||||
List<String> allHelperClasses = asList(instrumentationModule.getMuzzleHelperClassNames());
|
||||
List<String> allHelperClasses = instrumentationModule.getMuzzleHelperClassNames();
|
||||
if (!allHelperClasses.isEmpty()) {
|
||||
new HelperInjector(
|
||||
MuzzleGradlePluginUtil.class.getSimpleName(),
|
||||
|
@ -138,7 +137,7 @@ public final class MuzzleGradlePluginUtil {
|
|||
ServiceLoader.load(InstrumentationModule.class, instrumentationClassLoader)) {
|
||||
try {
|
||||
System.out.println(instrumentationModule.getClass().getName());
|
||||
for (ClassRef ref : instrumentationModule.getMuzzleReferences()) {
|
||||
for (ClassRef ref : instrumentationModule.getMuzzleReferences().values()) {
|
||||
System.out.print(prettyPrint(ref));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
|
|
|
@ -21,7 +21,6 @@ import io.opentelemetry.javaagent.tooling.muzzle.matcher.HelperReferenceWrapper.
|
|||
import io.opentelemetry.javaagent.tooling.muzzle.matcher.HelperReferenceWrapper.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
@ -45,12 +44,9 @@ public final class ReferenceMatcher {
|
|||
|
||||
public ReferenceMatcher(
|
||||
List<String> helperClassNames,
|
||||
ClassRef[] references,
|
||||
Map<String, ClassRef> references,
|
||||
Predicate<String> libraryInstrumentationPredicate) {
|
||||
this.references = new HashMap<>(references.length);
|
||||
for (ClassRef reference : references) {
|
||||
this.references.put(reference.getClassName(), reference);
|
||||
}
|
||||
this.references = references;
|
||||
this.helperClassNames = new HashSet<>(helperClassNames);
|
||||
this.instrumentationClassPredicate =
|
||||
new InstrumentationClassPredicate(libraryInstrumentationPredicate);
|
||||
|
|
|
@ -54,7 +54,7 @@ class ReferenceMatcherTest extends Specification {
|
|||
setup:
|
||||
def collector = new ReferenceCollector({ false })
|
||||
collector.collectReferencesFromAdvice(MethodBodyAdvice.name)
|
||||
def refMatcher = createMatcher(collector.getReferences().values())
|
||||
def refMatcher = createMatcher(collector.getReferences())
|
||||
|
||||
expect:
|
||||
getMismatchClassSet(refMatcher.getMismatchedReferenceSources(safeClasspath)).empty
|
||||
|
@ -92,8 +92,8 @@ class ReferenceMatcherTest extends Specification {
|
|||
def collector = new ReferenceCollector({ false })
|
||||
collector.collectReferencesFromAdvice(MethodBodyAdvice.name)
|
||||
|
||||
def refMatcher1 = createMatcher(collector.getReferences().values())
|
||||
def refMatcher2 = createMatcher(collector.getReferences().values())
|
||||
def refMatcher1 = createMatcher(collector.getReferences())
|
||||
def refMatcher2 = createMatcher(collector.getReferences())
|
||||
assert getMismatchClassSet(refMatcher1.getMismatchedReferenceSources(cl)).empty
|
||||
int countAfterFirstMatch = cl.count
|
||||
// the second matcher should be able to used cached type descriptions from the first
|
||||
|
@ -110,7 +110,7 @@ class ReferenceMatcherTest extends Specification {
|
|||
.build()
|
||||
|
||||
when:
|
||||
def mismatches = createMatcher([ref]).getMismatchedReferenceSources(this.class.classLoader)
|
||||
def mismatches = createMatcher([(ref.className): ref]).getMismatchedReferenceSources(this.class.classLoader)
|
||||
|
||||
then:
|
||||
getMismatchClassSet(mismatches) == expectedMismatches as Set
|
||||
|
@ -129,7 +129,7 @@ class ReferenceMatcherTest extends Specification {
|
|||
.build()
|
||||
|
||||
when:
|
||||
def mismatches = createMatcher([reference])
|
||||
def mismatches = createMatcher([(reference.className): reference])
|
||||
.getMismatchedReferenceSources(this.class.classLoader)
|
||||
|
||||
then:
|
||||
|
@ -153,7 +153,7 @@ class ReferenceMatcherTest extends Specification {
|
|||
.build()
|
||||
|
||||
when:
|
||||
def mismatches = createMatcher([reference])
|
||||
def mismatches = createMatcher([(reference.className): reference])
|
||||
.getMismatchedReferenceSources(this.class.classLoader)
|
||||
|
||||
then:
|
||||
|
@ -180,7 +180,7 @@ class ReferenceMatcherTest extends Specification {
|
|||
.build()
|
||||
|
||||
when:
|
||||
def mismatches = createMatcher([reference], [reference.className])
|
||||
def mismatches = createMatcher([(reference.className): reference], [reference.className])
|
||||
.getMismatchedReferenceSources(this.class.classLoader)
|
||||
|
||||
then:
|
||||
|
@ -200,7 +200,7 @@ class ReferenceMatcherTest extends Specification {
|
|||
.build()
|
||||
|
||||
when:
|
||||
def mismatches = createMatcher([reference], [reference.className])
|
||||
def mismatches = createMatcher([(reference.className): reference], [reference.className])
|
||||
.getMismatchedReferenceSources(this.class.classLoader)
|
||||
|
||||
then:
|
||||
|
@ -220,7 +220,7 @@ class ReferenceMatcherTest extends Specification {
|
|||
.build()
|
||||
|
||||
when:
|
||||
def mismatches = createMatcher([reference], [reference.className])
|
||||
def mismatches = createMatcher([(reference.className): reference], [reference.className])
|
||||
.getMismatchedReferenceSources(this.class.classLoader)
|
||||
|
||||
then:
|
||||
|
@ -242,7 +242,9 @@ class ReferenceMatcherTest extends Specification {
|
|||
.build()
|
||||
|
||||
when:
|
||||
def mismatches = createMatcher([reference, emptySuperClassRef], [reference.className, emptySuperClassRef.className])
|
||||
def mismatches = createMatcher(
|
||||
[(reference.className): reference, (emptySuperClassRef.className): emptySuperClassRef],
|
||||
[reference.className, emptySuperClassRef.className])
|
||||
.getMismatchedReferenceSources(this.class.classLoader)
|
||||
|
||||
then:
|
||||
|
@ -269,7 +271,9 @@ class ReferenceMatcherTest extends Specification {
|
|||
.build()
|
||||
|
||||
when:
|
||||
def mismatches = createMatcher([helper, baseHelper], [helper.className, baseHelper.className])
|
||||
def mismatches = createMatcher(
|
||||
[(helper.className): helper, (baseHelper.className): baseHelper],
|
||||
[helper.className, baseHelper.className])
|
||||
.getMismatchedReferenceSources(this.class.classLoader)
|
||||
|
||||
then:
|
||||
|
@ -289,7 +293,7 @@ class ReferenceMatcherTest extends Specification {
|
|||
.build()
|
||||
|
||||
when:
|
||||
def mismatches = createMatcher([helper], [helper.className])
|
||||
def mismatches = createMatcher([(helper.className): helper], [helper.className])
|
||||
.getMismatchedReferenceSources(this.class.classLoader)
|
||||
|
||||
then:
|
||||
|
@ -309,7 +313,7 @@ class ReferenceMatcherTest extends Specification {
|
|||
.build()
|
||||
|
||||
when:
|
||||
def mismatches = createMatcher([helper], [helper.className])
|
||||
def mismatches = createMatcher([(helper.className): helper], [helper.className])
|
||||
.getMismatchedReferenceSources(this.class.classLoader)
|
||||
|
||||
then:
|
||||
|
@ -323,9 +327,9 @@ class ReferenceMatcherTest extends Specification {
|
|||
"external helper, different field type" | "${TEST_EXTERNAL_INSTRUMENTATION_PACKAGE}.Helper" | "field" | "Lcom/external/DifferentType;"
|
||||
}
|
||||
|
||||
private static ReferenceMatcher createMatcher(Collection<ClassRef> references = [],
|
||||
private static ReferenceMatcher createMatcher(Map<String, ClassRef> references = [:],
|
||||
List<String> helperClasses = []) {
|
||||
new ReferenceMatcher(helperClasses, references as ClassRef[], { it.startsWith(TEST_EXTERNAL_INSTRUMENTATION_PACKAGE) })
|
||||
new ReferenceMatcher(helperClasses, references, { it.startsWith(TEST_EXTERNAL_INSTRUMENTATION_PACKAGE) })
|
||||
}
|
||||
|
||||
private static Set<Class> getMismatchClassSet(List<Mismatch> mismatches) {
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
package muzzle;
|
||||
|
||||
import io.opentelemetry.instrumentation.test.utils.GcUtils;
|
||||
import io.opentelemetry.javaagent.extension.muzzle.ClassRef;
|
||||
import io.opentelemetry.javaagent.tooling.muzzle.collector.ReferenceCollector;
|
||||
import io.opentelemetry.javaagent.tooling.muzzle.matcher.ReferenceMatcher;
|
||||
import java.lang.ref.WeakReference;
|
||||
|
@ -25,9 +24,9 @@ public class MuzzleWeakReferenceTest {
|
|||
WeakReference<ClassLoader> clRef = new WeakReference<>(loader);
|
||||
ReferenceCollector collector = new ReferenceCollector(className -> false);
|
||||
collector.collectReferencesFromAdvice(TestClasses.MethodBodyAdvice.class.getName());
|
||||
ClassRef[] refs = collector.getReferences().values().toArray(new ClassRef[0]);
|
||||
ReferenceMatcher refMatcher =
|
||||
new ReferenceMatcher(Collections.emptyList(), refs, className -> false);
|
||||
new ReferenceMatcher(
|
||||
Collections.emptyList(), collector.getReferences(), className -> false);
|
||||
refMatcher.getMismatchedReferenceSources(loader);
|
||||
loader = null;
|
||||
GcUtils.awaitGc(clRef);
|
||||
|
|
Loading…
Reference in New Issue