66 lines
2.6 KiB
Plaintext
66 lines
2.6 KiB
Plaintext
== Why is this an issue?
|
|
|
|
Denoted by the "@" symbol, annotations are metadata that can be added to classes, methods, and variables for various
|
|
purposes such as documentation, code analysis, and runtime processing.
|
|
|
|
Annotations have retention policies that determine in which context they are retained and available for use.
|
|
There are three retention policies for annotations:
|
|
|
|
* `RetentionPolicy.SOURCE` - Annotations are only available during compilation and code analysis.
|
|
They are not included in the compiled class file and are not available at runtime.
|
|
E.G. `@Override`, `@SuppressWarnings`
|
|
* `RetentionPolicy.CLASS` - Annotations are included in the compiled class file providing information to the compiler,
|
|
but they are not retained by the JVM at runtime. This is the default retention policy. E.G. `@PreviewFeature`
|
|
* `RetentionPolicy.RUNTIME` - Annotations are included in the compiled class file and available at runtime.
|
|
They can be accessed and used by the program through reflection.
|
|
E.G. `@FunctionalInterface`, `@Deprecated`
|
|
|
|
It is important to understand that only annotations having the `RUNTIME` retention policy can be accessed at runtime
|
|
using reflection. For example, the following if condition is true when the method argument is the
|
|
`java.util.function.Function` class:
|
|
|
|
[source,java]
|
|
----
|
|
void execute(Class<?> cls) {
|
|
if (cls.isAnnotationPresent(FunctionalInterface.class)) {
|
|
// ...
|
|
}
|
|
}
|
|
----
|
|
|
|
Therefore, it is an issue to use reflection in combination with annotations with the `SOURCE` or `CLASS` retention policy because they
|
|
are not present at runtime. For example, in the JVM source code, the `hashCode()` method of the `Integer` class has
|
|
the `@Override` annotation. However, the following if condition will always be false even if the method argument is the
|
|
`Integer#hashCode()` method because `@Override` has the `SOURCE` retention policy:
|
|
|
|
[source,java]
|
|
----
|
|
void execute(Method method) {
|
|
if (method.isAnnotationPresent(Override.class)) { // Noncompliant, if condition will always be false because
|
|
// @Override is declared with @Retention(RetentionPolicy.SOURCE)
|
|
// ...
|
|
}
|
|
}
|
|
----
|
|
|
|
This rule detects improper reflective access on annotations having the `SOURCE` or `CLASS` retention policy.
|
|
|
|
== Resources
|
|
|
|
=== Documentation
|
|
|
|
* https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/annotation/RetentionPolicy.html[Oracle SDK - java.lang.annotation.RetentionPolicy]
|
|
|
|
ifdef::env-github,rspecator-view[]
|
|
|
|
'''
|
|
== Implementation Specification
|
|
(visible only on this page)
|
|
|
|
=== Message
|
|
|
|
"@xxx" is not available at runtime and cannot be seen with reflection.
|
|
|
|
|
|
endif::env-github,rspecator-view[]
|