class BridgeClassLoader extends ClassLoader {
    private final ClassLoader internalClassSpace; // Bridging the internal lib class space as described in https://www.infoq.com/articles/code-generation-with-osgi
    private final Set<ClassLoader> additionalClassLoaders; // Additional Class Loaders in attempt to solve https://stackoverflow.com/questions/47854086/cglib-creating-class-proxy-in-osgi-results-in-noclassdeffounderror

    BridgeClassLoader(ClassLoader primary) {
      super(primary);
      internalClassSpace = ModelMapper.class.getClassLoader(); // ModelMapper's own ClassLoader must know how to load its internals
      additionalClassLoaders = Collections.newSetFromMap(new ConcurrentHashMap<ClassLoader, Boolean>());
    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
      if (name.startsWith("org.modelmapper.internal.cglib"))
        return internalClassSpace.loadClass(name);

      for (ClassLoader additionalClassLoader : additionalClassLoaders) {
        try {
          return additionalClassLoader.loadClass(name);
        }
        catch (ClassNotFoundException e) {
          // Don't mind... Attempt next class loader
        }
      }

      throw new ClassNotFoundException(name);
    }

    private void addAdditionalClassLoaders(Set<ClassLoader> additionalClassLoaders) {
      additionalClassLoaders.remove(this.getParent()); // Make sure that the parent ClassLoader is not part of the collection. Otherwise, a recursion might occur in findClass().
      this.additionalClassLoaders.addAll(additionalClassLoaders);
    }
  }

  private static final Map<ClassLoader, WeakReference<BridgeClassLoader>> CACHE = new WeakHashMap<ClassLoader, WeakReference<BridgeClassLoader>>();
  static ClassLoader getClassLoader(Class<?> appType) {
    Set<Class<?>> allExtendedOrImplementedTypesRecursively = getAllExtendedOrImplementedTypesRecursively(appType);
    Set<ClassLoader> allClassLoadersInTheTypeHierarchy = getAllClassLoadersInTheTypeHierarchy(allExtendedOrImplementedTypesRecursively);

    synchronized (BridgeClassLoaderFactory.class) {
      BridgeClassLoader bridgeClassLoader = null;
      WeakReference<BridgeClassLoader> bridgeClassLoaderRef = CACHE.get(appType.getClassLoader());
      if (bridgeClassLoaderRef != null) {
        bridgeClassLoader = bridgeClassLoaderRef.get();
      }

      if (bridgeClassLoader == null) {
        bridgeClassLoader = new BridgeClassLoader(appType.getClassLoader());
        CACHE.put(appType.getClassLoader(), new WeakReference<BridgeClassLoader>(bridgeClassLoader));
      }

      bridgeClassLoader.addAdditionalClassLoaders(allClassLoadersInTheTypeHierarchy);

      return bridgeClassLoader;
    }
  }

  private static Set<ClassLoader> getAllClassLoadersInTheTypeHierarchy(Set<Class<?>> allExtendedOrImplementedTypesRecursively) {
    Set<ClassLoader> result = new HashSet<ClassLoader>();
    for (Class<?> clazz : allExtendedOrImplementedTypesRecursively) {
      if (clazz.getClassLoader() != null) {
        result.add(clazz.getClassLoader());
      }
    }

    return result;
  }

  // Extracted from https://stackoverflow.com/questions/22031207/find-all-classes-and-interfaces-a-class-extends-or-implements-recursively
  private static Set<Class<?>> getAllExtendedOrImplementedTypesRecursively(Class<?> clazzArg) {<FILL_FUNCTION_BODY>

    Class<?> clazz = clazzArg;
    List<Class<?>> res = new ArrayList<Class<?>>();

    do {
      res.add(clazz);

      // First, add all the interfaces implemented by this class
      Class<?>[] interfaces = clazz.getInterfaces();
      if (interfaces.length > 0) {
        res.addAll(Arrays.asList(interfaces));

        for (Class<?> interfaze : interfaces) {
          res.addAll(getAllExtendedOrImplementedTypesRecursively(interfaze));
        }
      }

      // Add the super class
      Class<?> superClass = clazz.getSuperclass();

      // Interfaces does not have java,lang.Object as superclass, they have null, so break the cycle and return
      if (superClass == null) {
        break;
      }

      // Now inspect the superclass
      clazz = superClass;
    } while (!"java.lang.Object".equals(clazz.getCanonicalName()));

    return new HashSet<Class<?>>(res);
  
<no_super_class>