@Override
  public void generateClass($ClassVisitor v) {
    Class<?> sc = (superclass == null) ? Object.class : superclass;

    if (TypeUtils.isFinal(sc.getModifiers())) {
      throw new IllegalArgumentException("Cannot subclass final class " + sc);
    }
    List<Constructor<?>> constructors = new ArrayList<>(Arrays.asList(sc.getDeclaredConstructors()));
    filterConstructors(sc, constructors);

    // Order is very important: must add superclass, then
    // its superclass chain, then each interface and
    // its superinterfaces.
    final Set forcePublic = new HashSet<>();
    List<Method> actualMethods = new ArrayList<>();
    final Map<Method, Method> covariantMethods = new HashMap<>();
    getMethods(sc, interfaces, actualMethods, new ArrayList<>(), forcePublic);

    //Changes by Peter Gromov & Gregory Shrago

    for(Class aClass = sc; aClass != null; aClass = aClass.getSuperclass()) {
      for (final Method method : aClass.getDeclaredMethods()) {
        if (actualMethods.contains(method)) {
          removeAllCovariantMethods(actualMethods, method, covariantMethods);
        }
      }
    }


    ClassEmitter e = new ClassEmitter(v);
    e.begin_class(Constants.V1_2,
                  Constants.ACC_PUBLIC,
                  getClassName(),
                  $Type.getType(sc),
                  (useFactory ?
                   TypeUtils.add(TypeUtils.getTypes(interfaces), FACTORY) :
                   TypeUtils.getTypes(interfaces)),
                  Constants.SOURCE_FILE);
    List constructorInfo = CollectionUtils.transform(constructors, MethodInfoTransformer.getInstance());

    e.declare_field(Constants.ACC_PRIVATE, BOUND_FIELD, $Type.BOOLEAN_TYPE, null);
    if (!interceptDuringConstruction) {
      e.declare_field(Constants.ACC_PRIVATE, CONSTRUCTED_FIELD, $Type.BOOLEAN_TYPE, null);
    }
    e.declare_field(Constants.PRIVATE_FINAL_STATIC, THREAD_CALLBACKS_FIELD, THREAD_LOCAL, null);
    e.declare_field(Constants.PRIVATE_FINAL_STATIC, STATIC_CALLBACKS_FIELD, CALLBACK_ARRAY, null);

    for (int i = 0; i < callbackTypes.length; i++) {
      e.declare_field(Constants.ACC_PRIVATE, getCallbackField(i), callbackTypes[i], null);
    }
    final Map<Method, MethodInfo> methodInfoMap = new HashMap<>();
    for (Method method : actualMethods) {
      if (isJdk8DefaultMethod(method)) {
        continue;
      }
      int modifiers =
        Constants.ACC_FINAL | (method.getModifiers() & ~Constants.ACC_ABSTRACT & ~Constants.ACC_NATIVE & ~Constants.ACC_SYNCHRONIZED);
      if (forcePublic.contains(MethodWrapper.create(method))) {
        modifiers = (modifiers & ~Constants.ACC_PROTECTED) | Constants.ACC_PUBLIC;
      }
      if (covariantMethods.containsKey(method)) {
        modifiers |= Constants.ACC_BRIDGE;
      }
      methodInfoMap.put(method, ReflectUtils.getMethodInfo(method, modifiers));
    }

    emitMethods(e, methodInfoMap, covariantMethods);
    emitConstructors(e, constructorInfo);
    emitSetThreadCallbacks(e);
    emitSetStaticCallbacks(e);
    emitBindCallbacks(e);

    if (useFactory) {
      int[] keys = getCallbackKeys();
      emitNewInstanceCallbacks(e);
      emitNewInstanceCallback(e);
      emitNewInstanceMultiarg(e, constructorInfo);
      emitGetCallback(e, keys);
      emitSetCallback(e, keys);
      emitGetCallbacks(e);
      emitSetCallbacks(e);
    }

    e.end_class();
  }
@Override
  public void generateClass($ClassVisitor v)