A runtime-retained annotation can be read through reflection. Its presence is metadata; application code must still decide and enforce the associated behavior.
Java annotation retention: expose metadata without pretending it enforces policy
Operational contract
The marker targets methods and remains available at runtime. The lookup selects a method by name and parameter types, avoiding accidental selection of an overload. A true result means the annotation was declared on that method, not that access checks have run. The method handles an absent declaration by throwing NoSuchMethodException to its caller. A policy engine should bind permissions and authentication separately; an annotation alone is not an authorization boundary. Annotation inspection can be cached for stable classes if it sits on a hot request path.
Failure case
An invoice handler marks its approve(long) operation for auditing. Reflection finds the marker. The caller must still emit a durable audit record and deny unauthorized callers; an unannotated method should not quietly be treated as approved merely because no marker is present.
Java code
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
public class AuditMarkerInspection {
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface AuditRequired { }
public static final class InvoiceActions {
@AuditRequired public void approve(long invoiceId) { }
}
public static boolean marked(Class<?> owner, String methodName,
Class<?>... parameters) throws NoSuchMethodException {
return owner.getDeclaredMethod(methodName, parameters)
.isAnnotationPresent(AuditRequired.class);
}
}Performance and ownership cost
A reflective lookup scans or indexes class metadata according to the JVM implementation and can allocate Method objects. Treat it as setup work and cache a resolved policy if every request repeats it. Marker presence itself consumes little per-class metadata; the audit action has separate I/O cost.
Common Mistakes
- Do not assume an annotation performs its own enforcement.
- Do not inspect by name alone when overloads exist.
- Do not use SOURCE or CLASS retention when runtime reflection must read the marker.
Connected lessons
- Java annotations: retention and explicit processing
- Java reflection: inspect types without breaking contracts
- Java access control: private state and package boundaries
- Java repeatable annotations: read every declared routing label
- Java enum constant bodies: keep each fee rule with its tier
- Java generics and language contracts quiz
- Advanced Java
Continue with: Java trySetAccessible: handle a denied deep-reflection request.
