From afe22b84c27cc0ac20fd87dfbee9536a9216dec3 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Mon, 16 Dec 2019 16:49:39 +0100 Subject: [PATCH] ConcurrentReferenceHashMap cache for getInterfaceMethodIfPossible results Closes gh-24206 --- .../org/springframework/util/ClassUtils.java | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/spring-core/src/main/java/org/springframework/util/ClassUtils.java b/spring-core/src/main/java/org/springframework/util/ClassUtils.java index 3303f169f61..f9f7e65d67c 100644 --- a/spring-core/src/main/java/org/springframework/util/ClassUtils.java +++ b/spring-core/src/main/java/org/springframework/util/ClassUtils.java @@ -110,6 +110,11 @@ public abstract class ClassUtils { */ private static final Set> javaLanguageInterfaces; + /** + * Cache for equivalent methods on an interface implemented by the declaring class. + */ + private static final Map interfaceMethodCache = new ConcurrentReferenceHashMap<>(256); + static { primitiveWrapperTypeMap.put(Boolean.class, boolean.class); @@ -1291,13 +1296,16 @@ public abstract class ClassUtils { * @see #getMostSpecificMethod */ public static Method getInterfaceMethodIfPossible(Method method) { - if (Modifier.isPublic(method.getModifiers()) && !method.getDeclaringClass().isInterface()) { - Class current = method.getDeclaringClass(); + if (!Modifier.isPublic(method.getModifiers()) || method.getDeclaringClass().isInterface()) { + return method; + } + return interfaceMethodCache.computeIfAbsent(method, key -> { + Class current = key.getDeclaringClass(); while (current != null && current != Object.class) { Class[] ifcs = current.getInterfaces(); for (Class ifc : ifcs) { try { - return ifc.getMethod(method.getName(), method.getParameterTypes()); + return ifc.getMethod(key.getName(), key.getParameterTypes()); } catch (NoSuchMethodException ex) { // ignore @@ -1305,8 +1313,8 @@ public abstract class ClassUtils { } current = current.getSuperclass(); } - } - return method; + return key; + }); } /**