public MethodCallInfo(Method method, Method definition) {
    this.setMethod(method);
    // this.setDefinition(definition);
    this.setDeclaringClass(method.getDeclaringClass());
    symbolName = methodName;

    int modifiers = method.getModifiers();
    isStatic = Modifier.isStatic(modifiers);
    isVarArgs = method.isVarArgs();
    boolean isNative = Modifier.isNative(modifiers);
    boolean isVirtual = isAnnotationPresent(Virtual.class, definition);
    boolean isDirectModeAllowed =
        getInheritableAnnotation(DisableDirect.class, definition) == null
            && BridJ.isDirectModeEnabled();

    isCPlusPlus = !isStatic && derivesFrom(method.getDeclaringClass(), "org.bridj.cpp.CPPObject");
    isObjCBlock = !isStatic && derivesFrom(method.getDeclaringClass(), "org.bridj.objc.ObjCBlock");

    init(
        method,
        method.getReturnType(),
        method.getGenericReturnType(),
        method.getAnnotations(),
        method.getParameterTypes(),
        method.getGenericParameterTypes(),
        method.getParameterAnnotations(),
        isNative,
        isVirtual,
        isDirectModeAllowed);

    Convention cc = getInheritableAnnotation(Convention.class, definition);
    if (cc != null) {
      setCallingConvention(cc.value());
    }
    List<Class<?>> exceptionTypes = Arrays.asList(definition.getExceptionTypes());
    if (!exceptionTypes.isEmpty()) {
      this.direct = false; // there is no crash / exception protection for direct raw calls
      if (exceptionTypes.contains(LastError.class)) this.bThrowLastError = true;
    }
  }