Fail fast in the matcher, let the debug outputs use the cache
This commit is contained in:
parent
39e577ad97
commit
e65177a143
|
@ -42,14 +42,36 @@ public class ReferenceMatcher
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Matcher used by ByteBuddy. Fails fast and only caches empty results, or complete results
|
||||||
|
*
|
||||||
* @param loader Classloader to validate against (or null for bootstrap)
|
* @param loader Classloader to validate against (or null for bootstrap)
|
||||||
* @return true if all references match the classpath of loader
|
* @return true if all references match the classpath of loader
|
||||||
*/
|
*/
|
||||||
public boolean matches(final ClassLoader loader) {
|
public boolean matches(ClassLoader loader) {
|
||||||
return getMismatchedReferenceSources(loader).isEmpty();
|
if (loader == BOOTSTRAP_LOADER) {
|
||||||
|
loader = Utils.getBootstrapProxy();
|
||||||
|
}
|
||||||
|
|
||||||
|
final List<Mismatch> mismatches = new ArrayList<>(0);
|
||||||
|
|
||||||
|
for (final Reference reference : references) {
|
||||||
|
if (mismatches.size() > 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Don't reference-check helper classes.
|
||||||
|
// They will be injected by the instrumentation's HelperInjector.
|
||||||
|
if (!helperClassNames.contains(reference.getClassName())) {
|
||||||
|
mismatches.addAll(checkMatch(reference, loader));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mismatchCache.put(loader, mismatches);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Loads and caches the full list of mismatches. Used in debug contexts only
|
||||||
|
*
|
||||||
* @param loader Classloader to validate against (or null for bootstrap)
|
* @param loader Classloader to validate against (or null for bootstrap)
|
||||||
* @return A list of all mismatches between this ReferenceMatcher and loader's classpath.
|
* @return A list of all mismatches between this ReferenceMatcher and loader's classpath.
|
||||||
*/
|
*/
|
||||||
|
@ -82,7 +104,8 @@ public class ReferenceMatcher
|
||||||
* @param loader
|
* @param loader
|
||||||
* @return A list of mismatched sources. A list of size 0 means the reference matches the class.
|
* @return A list of mismatched sources. A list of size 0 means the reference matches the class.
|
||||||
*/
|
*/
|
||||||
public static List<Reference.Mismatch> checkMatch(Reference reference, ClassLoader loader) {
|
public static List<Reference.Mismatch> checkMatch(
|
||||||
|
final Reference reference, final ClassLoader loader) {
|
||||||
final TypePool typePool =
|
final TypePool typePool =
|
||||||
AgentTooling.poolStrategy()
|
AgentTooling.poolStrategy()
|
||||||
.typePool(AgentTooling.locationStrategy().classFileLocator(loader), loader);
|
.typePool(AgentTooling.locationStrategy().classFileLocator(loader), loader);
|
||||||
|
@ -96,7 +119,7 @@ public class ReferenceMatcher
|
||||||
reference.getSources().toArray(new Source[0]), reference.getClassName()));
|
reference.getSources().toArray(new Source[0]), reference.getClassName()));
|
||||||
}
|
}
|
||||||
return checkMatch(reference, resolution.resolve());
|
return checkMatch(reference, resolution.resolve());
|
||||||
} catch (Exception e) {
|
} catch (final Exception e) {
|
||||||
if (e.getMessage().startsWith("Cannot resolve type description for ")) {
|
if (e.getMessage().startsWith("Cannot resolve type description for ")) {
|
||||||
// bytebuddy throws an illegal state exception with this message if it cannot resolve types
|
// bytebuddy throws an illegal state exception with this message if it cannot resolve types
|
||||||
// TODO: handle missing type resolutions without catching bytebuddy's exceptions
|
// TODO: handle missing type resolutions without catching bytebuddy's exceptions
|
||||||
|
@ -112,10 +135,10 @@ public class ReferenceMatcher
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<Reference.Mismatch> checkMatch(
|
public static List<Reference.Mismatch> checkMatch(
|
||||||
Reference reference, TypeDescription typeOnClasspath) {
|
final Reference reference, final TypeDescription typeOnClasspath) {
|
||||||
final List<Mismatch> mismatches = new ArrayList<>(0);
|
final List<Mismatch> mismatches = new ArrayList<>(0);
|
||||||
|
|
||||||
for (Reference.Flag flag : reference.getFlags()) {
|
for (final Reference.Flag flag : reference.getFlags()) {
|
||||||
if (!flag.matches(typeOnClasspath.getModifiers())) {
|
if (!flag.matches(typeOnClasspath.getModifiers())) {
|
||||||
final String desc = reference.getClassName();
|
final String desc = reference.getClassName();
|
||||||
mismatches.add(
|
mismatches.add(
|
||||||
|
@ -127,8 +150,8 @@ public class ReferenceMatcher
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Reference.Field fieldRef : reference.getFields()) {
|
for (final Reference.Field fieldRef : reference.getFields()) {
|
||||||
FieldDescription.InDefinedShape fieldDescription = findField(fieldRef, typeOnClasspath);
|
final FieldDescription.InDefinedShape fieldDescription = findField(fieldRef, typeOnClasspath);
|
||||||
if (fieldDescription == null) {
|
if (fieldDescription == null) {
|
||||||
mismatches.add(
|
mismatches.add(
|
||||||
new Reference.Mismatch.MissingField(
|
new Reference.Mismatch.MissingField(
|
||||||
|
@ -137,7 +160,7 @@ public class ReferenceMatcher
|
||||||
fieldRef.getName(),
|
fieldRef.getName(),
|
||||||
fieldRef.getType().getInternalName()));
|
fieldRef.getType().getInternalName()));
|
||||||
} else {
|
} else {
|
||||||
for (Reference.Flag flag : fieldRef.getFlags()) {
|
for (final Reference.Flag flag : fieldRef.getFlags()) {
|
||||||
if (!flag.matches(fieldDescription.getModifiers())) {
|
if (!flag.matches(fieldDescription.getModifiers())) {
|
||||||
final String desc =
|
final String desc =
|
||||||
reference.getClassName()
|
reference.getClassName()
|
||||||
|
@ -155,7 +178,7 @@ public class ReferenceMatcher
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Reference.Method methodRef : reference.getMethods()) {
|
for (final Reference.Method methodRef : reference.getMethods()) {
|
||||||
final MethodDescription.InDefinedShape methodDescription =
|
final MethodDescription.InDefinedShape methodDescription =
|
||||||
findMethod(methodRef, typeOnClasspath);
|
findMethod(methodRef, typeOnClasspath);
|
||||||
if (methodDescription == null) {
|
if (methodDescription == null) {
|
||||||
|
@ -165,7 +188,7 @@ public class ReferenceMatcher
|
||||||
methodRef.getName(),
|
methodRef.getName(),
|
||||||
methodRef.getDescriptor()));
|
methodRef.getDescriptor()));
|
||||||
} else {
|
} else {
|
||||||
for (Reference.Flag flag : methodRef.getFlags()) {
|
for (final Reference.Flag flag : methodRef.getFlags()) {
|
||||||
if (!flag.matches(methodDescription.getModifiers())) {
|
if (!flag.matches(methodDescription.getModifiers())) {
|
||||||
final String desc =
|
final String desc =
|
||||||
reference.getClassName() + "#" + methodRef.getName() + methodRef.getDescriptor();
|
reference.getClassName() + "#" + methodRef.getName() + methodRef.getDescriptor();
|
||||||
|
@ -184,8 +207,8 @@ public class ReferenceMatcher
|
||||||
}
|
}
|
||||||
|
|
||||||
private static FieldDescription.InDefinedShape findField(
|
private static FieldDescription.InDefinedShape findField(
|
||||||
Reference.Field fieldRef, TypeDescription typeOnClasspath) {
|
final Reference.Field fieldRef, final TypeDescription typeOnClasspath) {
|
||||||
for (FieldDescription.InDefinedShape fieldType : typeOnClasspath.getDeclaredFields()) {
|
for (final FieldDescription.InDefinedShape fieldType : typeOnClasspath.getDeclaredFields()) {
|
||||||
if (fieldType.getName().equals(fieldRef.getName())
|
if (fieldType.getName().equals(fieldRef.getName())
|
||||||
&& fieldType
|
&& fieldType
|
||||||
.getType()
|
.getType()
|
||||||
|
@ -196,14 +219,14 @@ public class ReferenceMatcher
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (typeOnClasspath.getSuperClass() != null) {
|
if (typeOnClasspath.getSuperClass() != null) {
|
||||||
FieldDescription.InDefinedShape fieldOnSupertype =
|
final FieldDescription.InDefinedShape fieldOnSupertype =
|
||||||
findField(fieldRef, typeOnClasspath.getSuperClass().asErasure());
|
findField(fieldRef, typeOnClasspath.getSuperClass().asErasure());
|
||||||
if (fieldOnSupertype != null) {
|
if (fieldOnSupertype != null) {
|
||||||
return fieldOnSupertype;
|
return fieldOnSupertype;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (TypeDescription.Generic interfaceType : typeOnClasspath.getInterfaces()) {
|
for (final TypeDescription.Generic interfaceType : typeOnClasspath.getInterfaces()) {
|
||||||
FieldDescription.InDefinedShape fieldOnSupertype =
|
final FieldDescription.InDefinedShape fieldOnSupertype =
|
||||||
findField(fieldRef, interfaceType.asErasure());
|
findField(fieldRef, interfaceType.asErasure());
|
||||||
if (fieldOnSupertype != null) {
|
if (fieldOnSupertype != null) {
|
||||||
return fieldOnSupertype;
|
return fieldOnSupertype;
|
||||||
|
@ -213,8 +236,8 @@ public class ReferenceMatcher
|
||||||
}
|
}
|
||||||
|
|
||||||
private static MethodDescription.InDefinedShape findMethod(
|
private static MethodDescription.InDefinedShape findMethod(
|
||||||
Reference.Method methodRef, TypeDescription typeOnClasspath) {
|
final Reference.Method methodRef, final TypeDescription typeOnClasspath) {
|
||||||
for (MethodDescription.InDefinedShape methodDescription :
|
for (final MethodDescription.InDefinedShape methodDescription :
|
||||||
typeOnClasspath.getDeclaredMethods()) {
|
typeOnClasspath.getDeclaredMethods()) {
|
||||||
if (methodDescription.getInternalName().equals(methodRef.getName())
|
if (methodDescription.getInternalName().equals(methodRef.getName())
|
||||||
&& methodDescription.getDescriptor().equals(methodRef.getDescriptor())) {
|
&& methodDescription.getDescriptor().equals(methodRef.getDescriptor())) {
|
||||||
|
@ -222,14 +245,14 @@ public class ReferenceMatcher
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (typeOnClasspath.getSuperClass() != null) {
|
if (typeOnClasspath.getSuperClass() != null) {
|
||||||
MethodDescription.InDefinedShape methodOnSupertype =
|
final MethodDescription.InDefinedShape methodOnSupertype =
|
||||||
findMethod(methodRef, typeOnClasspath.getSuperClass().asErasure());
|
findMethod(methodRef, typeOnClasspath.getSuperClass().asErasure());
|
||||||
if (methodOnSupertype != null) {
|
if (methodOnSupertype != null) {
|
||||||
return methodOnSupertype;
|
return methodOnSupertype;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (TypeDescription.Generic interfaceType : typeOnClasspath.getInterfaces()) {
|
for (final TypeDescription.Generic interfaceType : typeOnClasspath.getInterfaces()) {
|
||||||
MethodDescription.InDefinedShape methodOnSupertype =
|
final MethodDescription.InDefinedShape methodOnSupertype =
|
||||||
findMethod(methodRef, interfaceType.asErasure());
|
findMethod(methodRef, interfaceType.asErasure());
|
||||||
if (methodOnSupertype != null) {
|
if (methodOnSupertype != null) {
|
||||||
return methodOnSupertype;
|
return methodOnSupertype;
|
||||||
|
|
Loading…
Reference in New Issue