public void dispatch(
      Object target, Object msg, Object sender, MissingMethodHandler missingMethodHandler)
      throws Exception {
    notNull(target, "target");

    Class targetClass = target.getClass();

    Method receiveMethod = findReceiveMethod(targetClass, msg.getClass());
    if (receiveMethod == null) {
      missingMethodHandler.onUnhandledMessage(msg, sender);
      return;
    }

    try {
      if (receiveMethod.getParameterTypes().length == 2) {
        receiveMethod.invoke(target, msg, sender);
      } else {
        receiveMethod.invoke(target, msg);
      }
    } catch (IllegalAccessException e) {
      // This will not be thrown since we make the receiveMethod accessible
      throw new RuntimeException(e);
    } catch (InvocationTargetException e) {
      throw Util.handle(e);
    }
  }