docs: public static Method getMatchingAccessibleMethod(
                                                  Class<?> clazz,
                                                  String methodName,
                                                  Class<?>[] parameterTypes) {
          // trace logging
          // Log log = LogFactory.getLog(MethodUtils.class); 
          if (log.isTraceEnabled()) {
              log.trace("Matching name=" + methodName + " on " + clazz);
          }
          MethodDescriptor md = new MethodDescriptor(clazz, methodName, parameterTypes, false);
  
          // see if we can find the method directly
          // most of the time this works and it's much faster
          try {
              // Check the cache first
              Method method = getCachedMethod(md);
              if (method != null) {
                  return method;
              }
  
              method = clazz.getMethod(methodName, parameterTypes);
              if (log.isTraceEnabled()) {
                  log.trace("Found straight match: " + method);
                  log.trace("isPublic:" + Modifier.isPublic(method.getModifiers()));
              }
  
              setMethodAccessible(method); // Default access superclass workaround
  
              cacheMethod(md, method);
              return method;
  
          } catch (NoSuchMethodException e) { /* SWALLOW */ }
  
          // search through all methods
          int paramSize = parameterTypes.length;
          Method bestMatch = null;
          Method[] methods = clazz.getMethods();
          float bestMatchCost = Float.MAX_VALUE;
          float myCost = Float.MAX_VALUE;
          for (int i = 0, size = methods.length; i < size ; i++) {
              if (methods[i].getName().equals(methodName)) {
                  // log some trace information
                  if (log.isTraceEnabled()) {
                      log.trace("Found matching name:");
                      log.trace(methods[i].toString());
                  }
  
                  // compare parameters
                  Class<?>[] methodsParams = methods[i].getParameterTypes();
                  int methodParamSize = methodsParams.length;
                  if (methodParamSize == paramSize) {
                      boolean match = true;
                      for (int n = 0 ; n < methodParamSize; n++) {
                          if (log.isTraceEnabled()) {
                              log.trace("Param=" + parameterTypes[n].getName());
                              log.trace("Method=" + methodsParams[n].getName());
                          }
                          if (!isAssignmentCompatible(methodsParams[n], parameterTypes[n])) {
                              if (log.isTraceEnabled()) {
                                  log.trace(methodsParams[n] + " is not assignable from "
                                              + parameterTypes[n]);
                              }
                              match = false;
                              break;
                          }
                      }
  
                      if (match) {
                          // get accessible version of method
                          Method method = getAccessibleMethod(clazz, methods[i]);
                          if (method != null) {
                              if (log.isTraceEnabled()) {
                                  log.trace(method + " accessible version of "
                                              + methods[i]);
                              }
                              setMethodAccessible(method); // Default access superclass workaround
                              myCost = getTotalTransformationCost(parameterTypes,method.getParameterTypes());
                              if ( myCost < bestMatchCost ) {
                                 bestMatch = method;
                                 bestMatchCost = myCost;
                              }
                          }
  
                          log.trace("Couldn't find accessible method.");
                      }
                  }
              }
          }
          if ( bestMatch != null ){
                   cacheMethod(md, bestMatch);
          } else {
          // didn't find a match
                 log.trace("No match found.");
          }
  
          return bestMatch;
      }