diff --git a/spring-context/src/main/java/org/springframework/context/support/AbstractApplicationContext.java b/spring-context/src/main/java/org/springframework/context/support/AbstractApplicationContext.java index 62eafb34da76..4ef8c78b27bf 100644 --- a/spring-context/src/main/java/org/springframework/context/support/AbstractApplicationContext.java +++ b/spring-context/src/main/java/org/springframework/context/support/AbstractApplicationContext.java @@ -1081,6 +1081,9 @@ protected void doClose() { // Let subclasses do some final clean-up if they wish... onClose(); + // Reset common introspection caches to avoid class reference leaks. + resetCommonCaches(); + // Reset local application listeners to pre-refresh state. if (this.earlyApplicationListeners != null) { this.applicationListeners.clear(); diff --git a/spring-core/src/main/java/org/springframework/core/annotation/AnnotationUtils.java b/spring-core/src/main/java/org/springframework/core/annotation/AnnotationUtils.java index 1818174ef98a..47baaae305ec 100644 --- a/spring-core/src/main/java/org/springframework/core/annotation/AnnotationUtils.java +++ b/spring-core/src/main/java/org/springframework/core/annotation/AnnotationUtils.java @@ -1326,6 +1326,9 @@ public static boolean isSynthesizedAnnotation(@Nullable Annotation annotation) { public static void clearCache() { AnnotationTypeMappings.clearCache(); AnnotationsScanner.clearCache(); + AttributeMethods.cache.clear(); + RepeatableContainers.cache.clear(); + OrderUtils.orderCache.clear(); } diff --git a/spring-core/src/main/java/org/springframework/core/annotation/AttributeMethods.java b/spring-core/src/main/java/org/springframework/core/annotation/AttributeMethods.java index dc122981aa0d..a828ebe44b5a 100644 --- a/spring-core/src/main/java/org/springframework/core/annotation/AttributeMethods.java +++ b/spring-core/src/main/java/org/springframework/core/annotation/AttributeMethods.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2022 the original author or authors. + * Copyright 2002-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -39,9 +39,7 @@ final class AttributeMethods { static final AttributeMethods NONE = new AttributeMethods(null, new Method[0]); - - private static final Map, AttributeMethods> cache = - new ConcurrentReferenceHashMap<>(); + static final Map, AttributeMethods> cache = new ConcurrentReferenceHashMap<>(); private static final Comparator methodComparator = (m1, m2) -> { if (m1 != null && m2 != null) { diff --git a/spring-core/src/main/java/org/springframework/core/annotation/OrderUtils.java b/spring-core/src/main/java/org/springframework/core/annotation/OrderUtils.java index bc38dcec195f..19fbc577b885 100644 --- a/spring-core/src/main/java/org/springframework/core/annotation/OrderUtils.java +++ b/spring-core/src/main/java/org/springframework/core/annotation/OrderUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2022 the original author or authors. + * Copyright 2002-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -41,7 +41,7 @@ public abstract class OrderUtils { private static final String JAVAX_PRIORITY_ANNOTATION = "jakarta.annotation.Priority"; /** Cache for @Order value (or NOT_ANNOTATED marker) per Class. */ - private static final Map orderCache = new ConcurrentReferenceHashMap<>(64); + static final Map orderCache = new ConcurrentReferenceHashMap<>(64); /** diff --git a/spring-core/src/main/java/org/springframework/core/annotation/RepeatableContainers.java b/spring-core/src/main/java/org/springframework/core/annotation/RepeatableContainers.java index 1b0293f05df6..adc33e3aa2ef 100644 --- a/spring-core/src/main/java/org/springframework/core/annotation/RepeatableContainers.java +++ b/spring-core/src/main/java/org/springframework/core/annotation/RepeatableContainers.java @@ -43,6 +43,8 @@ */ public abstract class RepeatableContainers { + static final Map, Object> cache = new ConcurrentReferenceHashMap<>(); + @Nullable private final RepeatableContainers parent; @@ -141,8 +143,6 @@ public static RepeatableContainers none() { */ private static class StandardRepeatableContainers extends RepeatableContainers { - private static final Map, Object> cache = new ConcurrentReferenceHashMap<>(); - private static final Object NONE = new Object(); private static final StandardRepeatableContainers INSTANCE = new StandardRepeatableContainers();