docs: public Object invoke(Object receiver, String methodName, /* @Nullable */ Object...args) throws SecurityException, IllegalArgumentException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
  		Preconditions.checkNotNull(receiver,"receiver");
  		Preconditions.checkNotNull(methodName,"methodName");
  		final Object[] arguments = args==null ? new Object[]{null}:args;
  		
  		Class<? extends Object> clazz = receiver.getClass();
  		Method compatible = null;
  		do {
  			for (Method candidate : clazz.getDeclaredMethods()) {
  				if (candidate != null && !candidate.isBridge() && isCompatible(candidate, methodName, arguments)) {
  					if (compatible != null) 
  						throw new IllegalStateException("Ambiguous methods to invoke. Both "+compatible+" and  "+candidate+" would be compatible choices.");
  					compatible = candidate;
  				}
  			}
  		} while(compatible == null && (clazz = clazz.getSuperclass()) != null);
  		if (compatible != null) {
  			if (!compatible.isAccessible())
  				compatible.setAccessible(true);
  			return compatible.invoke(receiver, arguments);
  		}
  		// not found provoke method not found exception
  		Class<?>[] paramTypes = new Class<?>[arguments.length];
  		for (int i = 0; i< arguments.length ; i++) {
  			paramTypes[i] = arguments[i] == null ? Object.class : arguments[i].getClass();
  		}
  		Method method = receiver.getClass().getMethod(methodName, paramTypes);
  		return method.invoke(receiver, arguments);
  	}