diff --git a/class-match/src/main/java/datadog/instrument/classmatch/AccessMatcher.java b/class-match/src/main/java/datadog/instrument/classmatch/AccessMatcher.java
new file mode 100644
index 0000000..0015df6
--- /dev/null
+++ b/class-match/src/main/java/datadog/instrument/classmatch/AccessMatcher.java
@@ -0,0 +1,89 @@
+/*
+ * Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License.
+ * This product includes software developed at Datadog (https://www.datadoghq.com/).
+ * Copyright 2025-Present Datadog, Inc.
+ */
+
+package datadog.instrument.classmatch;
+
+import java.lang.reflect.Modifier;
+import java.util.function.IntPredicate;
+
+/**
+ * Predicate for matching access modifiers defined in class-files.
+ */
+@FunctionalInterface
+public interface AccessMatcher extends IntPredicate {
+
+ /** Matches public access. */
+ AccessMatcher PUBLIC = Modifier::isPublic;
+
+ /** Matches private access. */
+ AccessMatcher PRIVATE = Modifier::isPrivate;
+
+ /** Matches protected access. */
+ AccessMatcher PROTECTED = Modifier::isProtected;
+
+ /** Matches package-private access. */
+ AccessMatcher PACKAGE_PRIVATE =
+ acc -> (acc & (Modifier.PUBLIC | Modifier.PROTECTED | Modifier.PRIVATE)) == 0;
+
+ /** Matches static methods/fields. */
+ AccessMatcher STATIC = Modifier::isStatic;
+
+ /** Matches non-static methods/fields. */
+ AccessMatcher INSTANCE = acc -> (acc & Modifier.STATIC) == 0;
+
+ /** Matches final classes/methods/fields. */
+ AccessMatcher FINAL = Modifier::isFinal;
+
+ /** Matches non-final classes/methods/fields. */
+ AccessMatcher NON_FINAL = acc -> (acc & Modifier.FINAL) == 0;
+
+ /** Matches synchronized methods. */
+ AccessMatcher SYNCHRONIZED = Modifier::isSynchronized;
+
+ /** Matches varargs methods. */
+ AccessMatcher VARARGS = acc -> (acc & 0x0080) != 0;
+
+ /** Matches volatile fields. */
+ AccessMatcher VOLATILE = Modifier::isVolatile;
+
+ /** Matches transient fields. */
+ AccessMatcher TRANSIENT = Modifier::isTransient;
+
+ /** Matches interface classes. */
+ AccessMatcher INTERFACE = Modifier::isInterface;
+
+ /** Matches non-interface classes. */
+ AccessMatcher CLASS = acc -> (acc & Modifier.INTERFACE) == 0;
+
+ /** Matches abstract classes/methods. */
+ AccessMatcher ABSTRACT = Modifier::isAbstract;
+
+ /** Matches non-abstract classes/methods. */
+ AccessMatcher CONCRETE = acc -> (acc & Modifier.ABSTRACT) == 0;
+
+ /**
+ * Conjunction of this matcher AND another.
+ *
+ * @param other the other matcher
+ * @return conjunction of both matchers
+ */
+ default AccessMatcher and(AccessMatcher other) {
+ // simple approach as we don't expect many access-matcher unions
+ return acc -> test(acc) && other.test(acc);
+ }
+
+ /**
+ * Disjunction of this matcher OR another.
+ *
+ * @param other the other matcher
+ * @return disjunction of both matchers
+ */
+ default AccessMatcher or(AccessMatcher other) {
+ // simple approach as we don't expect many access-matcher unions
+ return acc -> test(acc) || other.test(acc);
+ }
+}
diff --git a/class-match/src/main/java/datadog/instrument/classmatch/ClassMatcher.java b/class-match/src/main/java/datadog/instrument/classmatch/ClassMatcher.java
index 837d66a..7aed30e 100644
--- a/class-match/src/main/java/datadog/instrument/classmatch/ClassMatcher.java
+++ b/class-match/src/main/java/datadog/instrument/classmatch/ClassMatcher.java
@@ -12,7 +12,6 @@
import static java.util.Arrays.asList;
import java.util.Collection;
-import java.util.function.IntPredicate;
import java.util.function.Predicate;
/** Fluent-API for building {@link ClassOutline} predicates. */
@@ -36,7 +35,7 @@ static ClassMatcher declares(FieldMatcher fieldMatcher) {
* @param fieldMatcher the field matcher
* @return matcher of classes with a matching field
*/
- static ClassMatcher declares(IntPredicate accessMatcher, FieldMatcher fieldMatcher) {
+ static ClassMatcher declares(AccessMatcher accessMatcher, FieldMatcher fieldMatcher) {
FieldMatcher combinedMatcher = fieldMatcher.access(accessMatcher);
return c -> anyMatch(c.fields, combinedMatcher);
}
@@ -58,7 +57,7 @@ static ClassMatcher declares(MethodMatcher methodMatcher) {
* @param methodMatcher the method matcher
* @return matcher of classes with a matching method
*/
- static ClassMatcher declares(IntPredicate accessMatcher, MethodMatcher methodMatcher) {
+ static ClassMatcher declares(AccessMatcher accessMatcher, MethodMatcher methodMatcher) {
MethodMatcher combinedMatcher = methodMatcher.access(accessMatcher);
return c -> anyMatch(c.methods, combinedMatcher);
}
diff --git a/class-match/src/main/java/datadog/instrument/classmatch/FieldMatcher.java b/class-match/src/main/java/datadog/instrument/classmatch/FieldMatcher.java
index fe4c108..742b375 100644
--- a/class-match/src/main/java/datadog/instrument/classmatch/FieldMatcher.java
+++ b/class-match/src/main/java/datadog/instrument/classmatch/FieldMatcher.java
@@ -8,7 +8,6 @@
import static datadog.instrument.classmatch.InternalMatchers.descriptor;
-import java.util.function.IntPredicate;
import java.util.function.Predicate;
/** Fluent-API for building {@link FieldOutline} predicates. */
@@ -41,7 +40,7 @@ static FieldMatcher field(Predicate nameMatcher) {
* @param accessMatcher the access matcher
* @return matcher of fields with matching access
*/
- default FieldMatcher access(IntPredicate accessMatcher) {
+ default FieldMatcher access(AccessMatcher accessMatcher) {
return f -> test(f) && accessMatcher.test(f.access);
}
diff --git a/class-match/src/main/java/datadog/instrument/classmatch/MethodMatcher.java b/class-match/src/main/java/datadog/instrument/classmatch/MethodMatcher.java
index 7e9a8eb..7235bd0 100644
--- a/class-match/src/main/java/datadog/instrument/classmatch/MethodMatcher.java
+++ b/class-match/src/main/java/datadog/instrument/classmatch/MethodMatcher.java
@@ -16,7 +16,6 @@
import static java.util.Arrays.asList;
import java.util.Collection;
-import java.util.function.IntPredicate;
import java.util.function.Predicate;
/** Fluent-API for building {@link MethodOutline} predicates. */
@@ -76,7 +75,7 @@ static MethodMatcher staticInitializer() {
* @param accessMatcher the access matcher
* @return matcher of methods with matching access
*/
- default MethodMatcher access(IntPredicate accessMatcher) {
+ default MethodMatcher access(AccessMatcher accessMatcher) {
return and(m -> accessMatcher.test(m.access));
}
diff --git a/class-match/src/main/java/datadog/instrument/classmatch/StandardMatchers.java b/class-match/src/main/java/datadog/instrument/classmatch/StandardMatchers.java
index 1fefda2..958551e 100644
--- a/class-match/src/main/java/datadog/instrument/classmatch/StandardMatchers.java
+++ b/class-match/src/main/java/datadog/instrument/classmatch/StandardMatchers.java
@@ -8,58 +8,63 @@
import static java.util.Arrays.asList;
-import java.lang.reflect.Modifier;
import java.util.Collection;
import java.util.HashSet;
-import java.util.function.IntPredicate;
import java.util.function.Predicate;
/** Standard matchers, part of the public API. */
public final class StandardMatchers {
- /** Matches public access. */
- public static final IntPredicate PUBLIC = Modifier::isPublic;
-
- /** Matches private access. */
- public static final IntPredicate PRIVATE = Modifier::isPrivate;
-
- /** Matches protected access. */
- public static final IntPredicate PROTECTED = Modifier::isProtected;
-
- /** Matches static access. */
- public static final IntPredicate STATIC = Modifier::isStatic;
-
- /** Matches final classes/methods/fields. */
- public static final IntPredicate FINAL = Modifier::isFinal;
-
- /** Matches synchronized methods. */
- public static final IntPredicate SYNCHRONIZED = Modifier::isSynchronized;
-
- /** Matches volatile fields. */
- public static final IntPredicate VOLATILE = Modifier::isVolatile;
-
- /** Matches transient fields. */
- public static final IntPredicate TRANSIENT = Modifier::isTransient;
+ private StandardMatchers() {}
- /** Matches native methods. */
- public static final IntPredicate NATIVE = Modifier::isNative;
+ /**
+ * Negates the given type matcher.
+ *
+ * @param matcher the matcher to negate
+ * @return negation of the matcher
+ */
+ public static TypeMatcher not(TypeMatcher matcher) {
+ return cs -> !matcher.test(cs);
+ }
- /** Matches interface classes. */
- public static final IntPredicate INTERFACE = Modifier::isInterface;
+ /**
+ * Negates the given class matcher.
+ *
+ * @param matcher the matcher to negate
+ * @return negation of the matcher
+ */
+ public static ClassMatcher not(ClassMatcher matcher) {
+ return c -> !matcher.test(c);
+ }
- /** Matches abstract classes. */
- public static final IntPredicate ABSTRACT = Modifier::isAbstract;
+ /**
+ * Negates the given field matcher.
+ *
+ * @param matcher the matcher to negate
+ * @return negation of the matcher
+ */
+ public static FieldMatcher not(FieldMatcher matcher) {
+ return f -> !matcher.test(f);
+ }
- private StandardMatchers() {}
+ /**
+ * Negates the given method matcher.
+ *
+ * @param matcher the matcher to negate
+ * @return negation of the matcher
+ */
+ public static MethodMatcher not(MethodMatcher matcher) {
+ return m -> !matcher.test(m);
+ }
/**
- * Syntactic sugar around {@link IntPredicate#negate()}.
+ * Negates the given access matcher.
*
- * @param predicate the predicate to negate
- * @return negated predicate
+ * @param matcher the matcher to negate
+ * @return negation of the matcher
*/
- public static IntPredicate not(IntPredicate predicate) {
- return predicate.negate();
+ public static AccessMatcher not(AccessMatcher matcher) {
+ return acc -> !matcher.test(acc);
}
/**
diff --git a/class-match/src/main/java/datadog/instrument/classmatch/TypeMatcher.java b/class-match/src/main/java/datadog/instrument/classmatch/TypeMatcher.java
index af1ea37..54eedaa 100644
--- a/class-match/src/main/java/datadog/instrument/classmatch/TypeMatcher.java
+++ b/class-match/src/main/java/datadog/instrument/classmatch/TypeMatcher.java
@@ -13,6 +13,7 @@
import java.util.function.Predicate;
/** Fluent-API for building type hierarchy predicates. */
+@FunctionalInterface
public interface TypeMatcher extends Predicate {
/**