ConcurrentReferenceHashMap cache for getInterfaceMethodIfPossible results

Closes gh-24206
This commit is contained in:
Juergen Hoeller
2019-12-16 16:49:39 +01:00
parent 634aba4ab6
commit afe22b84c2

View File

@@ -110,6 +110,11 @@ public abstract class ClassUtils {
*/
private static final Set<Class<?>> javaLanguageInterfaces;
/**
* Cache for equivalent methods on an interface implemented by the declaring class.
*/
private static final Map<Method, Method> 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;
});
}
/**