Make TYPE_HIERARCHY_AND_ENCLOSING_CLASSES annotation search strategy defensive
Prior to this commit, when searching for annotations using the TYPE_HIERARCHY_AND_ENCLOSING_CLASSES strategy an exception could be thrown while attempting to load the enclosing class (e.g., a NoClassDefFoundError), thereby halting the entire annotation scanning process. This commit makes this search strategy defensive by logging exceptions encountered while processing the enclosing class hierarchy instead of allowing the exception to halt the entire annotation scanning process. The exception handling is performed by AnnotationUtils.handleIntrospectionFailure() which only allows an AnnotationConfigurationException to propagate. See gh-24136
This commit is contained in:
@@ -1087,16 +1087,17 @@ public abstract class AnnotationUtils {
|
||||
* <p>If the supplied exception is an {@link AnnotationConfigurationException},
|
||||
* it will simply be thrown, allowing it to propagate to the caller, and
|
||||
* nothing will be logged.
|
||||
* <p>Otherwise, this method logs an introspection failure (in particular
|
||||
* {@code TypeNotPresentExceptions}) before moving on, assuming nested
|
||||
* Class values were not resolvable within annotation attributes and
|
||||
* <p>Otherwise, this method logs an introspection failure (in particular for
|
||||
* a {@link TypeNotPresentException}) before moving on, assuming nested
|
||||
* {@code Class} values were not resolvable within annotation attributes and
|
||||
* thereby effectively pretending there were no annotations on the specified
|
||||
* element.
|
||||
* @param element the element that we tried to introspect annotations on
|
||||
* @param ex the exception that we encountered
|
||||
* @see #rethrowAnnotationConfigurationException
|
||||
* @see IntrospectionFailureLogger
|
||||
*/
|
||||
private static void handleIntrospectionFailure(@Nullable AnnotatedElement element, Throwable ex) {
|
||||
static void handleIntrospectionFailure(@Nullable AnnotatedElement element, Throwable ex) {
|
||||
rethrowAnnotationConfigurationException(ex);
|
||||
IntrospectionFailureLogger logger = IntrospectionFailureLogger.INFO;
|
||||
boolean meta = false;
|
||||
|
||||
@@ -231,14 +231,24 @@ abstract class AnnotationsScanner {
|
||||
}
|
||||
}
|
||||
if (includeEnclosing) {
|
||||
Class<?> enclosingClass = source.getEnclosingClass();
|
||||
if (enclosingClass != null) {
|
||||
R enclosingResult = processClassHierarchy(context, aggregateIndex,
|
||||
enclosingClass, processor, classFilter, includeInterfaces, true);
|
||||
if (enclosingResult != null) {
|
||||
return enclosingResult;
|
||||
// Since merely attempting to load the enclosing class may result in
|
||||
// automatic loading of sibling nested classes that in turn results
|
||||
// in an exception such as NoClassDefFoundError, we wrap the following
|
||||
// in its own dedicated try-catch block in order not to preemptively
|
||||
// halt the annotation scanning process.
|
||||
try {
|
||||
Class<?> enclosingClass = source.getEnclosingClass();
|
||||
if (enclosingClass != null) {
|
||||
R enclosingResult = processClassHierarchy(context, aggregateIndex,
|
||||
enclosingClass, processor, classFilter, includeInterfaces, true);
|
||||
if (enclosingResult != null) {
|
||||
return enclosingResult;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
AnnotationUtils.handleIntrospectionFailure(source, ex);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user