@@ -1483,8 +1483,8 @@ private static Method findInterfaceMethodIfPossible(String methodName, Class<?>[
14831483 }
14841484
14851485 /**
1486- * Get the highest publicly accessible method in the supplied method's type hierarchy that
1487- * has a method signature equivalent to the supplied method, if possible.
1486+ * Get the closest publicly accessible (and exported) method in the supplied method's type
1487+ * hierarchy that has a method signature equivalent to the supplied method, if possible.
14881488 * <p>Otherwise, this method recursively searches the class hierarchy and implemented
14891489 * interfaces for an equivalent method that is {@code public} and declared in a
14901490 * {@code public} type.
@@ -1507,18 +1507,21 @@ private static Method findInterfaceMethodIfPossible(String methodName, Class<?>[
15071507 * @see #getMostSpecificMethod(Method, Class)
15081508 */
15091509 public static Method getPubliclyAccessibleMethodIfPossible (Method method , @ Nullable Class <?> targetClass ) {
1510- // If the method is not public, we can abort the search immediately.
1511- if (!Modifier .isPublic (method .getModifiers ())) {
1510+ Class <?> declaringClass = method .getDeclaringClass ();
1511+ // If the method is not public or its declaring class is public and exported already,
1512+ // we can abort the search immediately (avoiding reflection as well as cache access).
1513+ if (!Modifier .isPublic (method .getModifiers ()) || (Modifier .isPublic (declaringClass .getModifiers ()) &&
1514+ declaringClass .getModule ().isExported (declaringClass .getPackageName (), ClassUtils .class .getModule ()))) {
15121515 return method ;
15131516 }
15141517
15151518 Method interfaceMethod = getInterfaceMethodIfPossible (method , targetClass , true );
15161519 // If we found a method in a public interface, return the interface method.
1517- if (interfaceMethod != method ) {
1520+ if (interfaceMethod != method && interfaceMethod .getDeclaringClass ().getModule ().isExported (
1521+ interfaceMethod .getDeclaringClass ().getPackageName (), ClassUtils .class .getModule ())) {
15181522 return interfaceMethod ;
15191523 }
15201524
1521- Class <?> declaringClass = method .getDeclaringClass ();
15221525 // Bypass cache for java.lang.Object unless it is actually an overridable method declared there.
15231526 if (declaringClass .getSuperclass () == Object .class && !ReflectionUtils .isObjectMethod (method )) {
15241527 return method ;
@@ -1540,7 +1543,9 @@ private static Method findPubliclyAccessibleMethodIfPossible(
15401543 if (method == null ) {
15411544 break ;
15421545 }
1543- if (Modifier .isPublic (method .getDeclaringClass ().getModifiers ())) {
1546+ if (Modifier .isPublic (method .getDeclaringClass ().getModifiers ()) &&
1547+ method .getDeclaringClass ().getModule ().isExported (
1548+ method .getDeclaringClass ().getPackageName (), ClassUtils .class .getModule ())) {
15441549 result = method ;
15451550 }
15461551 current = method .getDeclaringClass ().getSuperclass ();
0 commit comments