docs: private Method findHandlerMethod(Object target, Class<? extends IEvents> eventsClass,
              String eventName, Object[] params) {
          // Use cached method if available. Note: no further type checking is done if the
          // method has been cached. It will be checked by JRE when the method is invoked.
          Method cachedMethod = getCachedMethod(target, eventName);
          if (cachedMethod != null) {
              return cachedMethod;
          }
  
          // Check the event and params against the eventsClass interface object.
          Method nameMatch = null;
          Method signatureMatch = null;
          for (Method method : eventsClass.getMethods()) {
              // Match method name and event name
              if (method.getName().equals(eventName)) {
                  nameMatch = method;
  
                  // Check number of parameters
                  Class<?>[] types = method.getParameterTypes();
                  if (types.length != params.length)
                      continue;
  
                  // Check parameter types
                  int i = 0;
                  boolean foundMatchedMethod = true;
                  for (Class<?> type : types) {
                      Object param = params[i++];
                      if (!isInstanceWithAutoboxing(type, param)) {
                          foundMatchedMethod = false;
                          break;
                      }
                  }
  
                  if (foundMatchedMethod) {
                      signatureMatch = method;
                      break;
                  }
              }
          }
  
          // Error
          if (nameMatch == null) {
              throw new RuntimeException(String.format("The interface contains no method %s", eventName));
          } else if (signatureMatch == null ){
              throw new RuntimeException(String.format("The interface contains a method %s but "
                      + "parameters don't match", eventName));
          }
  
          // Cache the method for the target, even if it doesn't implement the interface. This is
          // to avoid always verifying the event.
          addCachedMethod(target, eventName, signatureMatch);
  
          return signatureMatch;
      }