in core/src/main/java/hudson/Util.java [1463:1507]
private static Method getMethod(@NonNull Class<?> clazz, @Nullable Class<?> base, @NonNull String methodName, @NonNull Class<?>... types) {
try {
final Method res = clazz.getDeclaredMethod(methodName, types);
final int mod = res.getModifiers();
// private and static methods are never ok, and end the search
if (Modifier.isPrivate(mod) || Modifier.isStatic(mod)) {
return null;
}
// when looking for the base/declaring method, final is not ok
if (base == null && Modifier.isFinal(mod)) {
return null;
}
// when looking for the overriding method, abstract is not ok
if (base != null && Modifier.isAbstract(mod)) {
return null;
}
return res;
} catch (NoSuchMethodException e) {
// If the base is an interface, the implementation may come from a default implementation on a derived
// interface. So look at interfaces too.
if (base != null && Modifier.isInterface(base.getModifiers())) {
for (Class<?> iface : clazz.getInterfaces()) {
if (base.equals(iface) || !base.isAssignableFrom(iface)) {
continue;
}
final Method defaultImpl = Util.getMethod(iface, base, methodName, types);
if (defaultImpl != null) {
return defaultImpl;
}
}
}
// Method not found in clazz, let's search in superclasses
Class<?> superclass = clazz.getSuperclass();
if (superclass != null) {
// if the superclass doesn't derive from base anymore (or IS base), stop looking
if (base != null && (base.equals(superclass) || !base.isAssignableFrom(superclass))) {
return null;
}
return getMethod(superclass, base, methodName, types);
}
return null;
} catch (SecurityException e) {
throw new AssertionError(e);
}
}