private static <T, G extends T> void generateConstructorsAndFields(
      DexMaker dexMaker, TypeId<G> generatedType, TypeId<T> superType, Class<T> superClass) {
    TypeId<InvocationHandler> handlerType = TypeId.get(InvocationHandler.class);
    TypeId<Method[]> methodArrayType = TypeId.get(Method[].class);
    FieldId<G, InvocationHandler> handlerField =
        generatedType.getField(handlerType, FIELD_NAME_HANDLER);
    dexMaker.declare(handlerField, PRIVATE, null);
    FieldId<G, Method[]> allMethods = generatedType.getField(methodArrayType, FIELD_NAME_METHODS);
    dexMaker.declare(allMethods, PRIVATE | STATIC, null);
    for (Constructor<T> constructor : getConstructorsToOverwrite(superClass)) {
      if (constructor.getModifiers() == Modifier.FINAL) {
        continue;
      }
      TypeId<?>[] types = classArrayToTypeArray(constructor.getParameterTypes());
      MethodId<?, ?> method = generatedType.getConstructor(types);
      Code constructorCode = dexMaker.declare(method, PUBLIC);
      Local<G> thisRef = constructorCode.getThis(generatedType);
      Local<?>[] params = new Local[types.length];
      for (int i = 0; i < params.length; ++i) {
        params[i] = constructorCode.getParameter(i, types[i]);
      }
      MethodId<T, ?> superConstructor = superType.getConstructor(types);
      constructorCode.invokeDirect(superConstructor, null, thisRef, params);
      constructorCode.returnVoid();
    }
  }
The super method must include the return type, otherwise its ambiguous for methods with
covariant return types.
android/android_framework/dex-maker/src/main/java/com/android/dx/stock/ProxyBuilder.java