I needed to dynamically load and instantiate some classes from a generated jar and a generated .class file which depends on that jar. So I came up with this: ```java package ytm.yajco.translation.util; import org.jetbrains.annotations.NotNull; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; import java.nio.file.Path; import static java.lang.StackWalker.Option.RETAIN_CLASS_REFERENCE; public class DynamicClass { protected static final StackWalker walker = StackWalker.getInstance(RETAIN_CLASS_REFERENCE); protected final Class<?> loadedClass; /** * <b>WARNING:</b> Do not call this constructor if {@code jar} has already been loaded. * This will avoid multiple class loading. * <p> * Creates a new class loader which can load classes from {@code jar}. * The new classloader inherits the classpath from the class loader of the caller of this constructor. * Finally, the sought class is loaded from the given {@code jar}. * * @param classFQN fully qualified name of the class to be loaded * @param jar path to the jar or root directory where {@code classFQN} is to be found * @see StackWalker#getCallerClass() */ public DynamicClass(String classFQN, @NotNull Path jar) throws MalformedURLException, ReflectiveOperationException { this(classFQN, jar, walker.getCallerClass().getClassLoader()); } /** * <b>WARNING:</b> Do not call this constructor if {@code jar} has already been loaded by {@code parentCL} * or its ancestors. This will avoid multiple class loading. * <p> * Creates a new class loader which can load classes from {@code jar}. * The new classloader inherits the classpath from {@code parentCL}. * Finally, the sought class is loaded from the given {@code jar}. * * @param classFQN fully qualified name of the class to be loaded * @param jar path to the jar or root directory where {@code classFQN} is to be found * @param parentCL classloader to use as a parent */ public DynamicClass(String classFQN, @NotNull Path jar, ClassLoader parentCL) throws MalformedURLException, ClassNotFoundException { final URL[] jarLocation = {jar.toUri().toURL()}; final URLClassLoader classLoader = URLClassLoader.newInstance(jarLocation, parentCL); loadedClass = Class.forName(classFQN, true, classLoader); } /** * Finds the sought class using the given class loader. * * @param classFQN fully qualified name of the class to be loaded * @param classLoader class loader to reuse * @throws ClassNotFoundException if the class cannot be located by the specified class loader */ public DynamicClass(String classFQN, ClassLoader classLoader) throws ClassNotFoundException { loadedClass = Class.forName(classFQN, true, classLoader); } public Class<?> getLoadedClass() { return loadedClass; } public ClassLoader getClassLoader() { return loadedClass.getClassLoader(); } } ``` In one of the cases I know the interface statically so in my `DynamicSupplier` subclass: ```java public Supplier<?> newSupplierInstance() throws ReflectiveOperationException { return (Supplier<?>) loadedClass.getDeclaredConstructor().newInstance(); } ``` In the other case I know the method signatures, so I have provided methods to which hide the reflective access. Also I wrap the new instance in a small class (maybe an adapter?) just to put an abstract layer when working with a bare `Object`. ```java package ytm.yajco.translation.language; import org.jetbrains.annotations.NotNull; import ytm.yajco.translation.util.DynamicClass; import java.io.Reader; import java.lang.reflect.Method; import java.net.MalformedURLException; import java.nio.file.Path; public class DynamicParser extends DynamicClass { // skipped JavaDoc for brevity in this review public DynamicParser(String parserFQN, @NotNull Path parserJar) throws MalformedURLException, ReflectiveOperationException { this(parserFQN, parserJar, walker.getCallerClass().getClassLoader()); } // skipped other constructors matching super for brevity in this review public static Object parseSentence(@NotNull Object parser, String sentence) throws ReflectiveOperationException { final Method parse = parser.getClass().getMethod("parse", String.class); return parse.invoke(parser, sentence); } public static Object parseSentence(@NotNull Object parser, Reader sentence) throws ReflectiveOperationException { final Method parse = parser.getClass().getMethod("parse", Reader.class); return parse.invoke(parser, sentence); } public Parser newParserInstance() throws ReflectiveOperationException { final Object parser = loadedClass.getDeclaredConstructor().newInstance(); return new Parser(parser); } public static class Parser { private final Object parser; private Parser(Object parser) { this.parser = parser; } public Object parseSentence(String sentence) throws ReflectiveOperationException { return DynamicParser.parseSentence(parser, sentence); } public Object parseSentence(Reader sentence) throws ReflectiveOperationException { return DynamicParser.parseSentence(parser, sentence); } public Object getRealParser() { return parser; } } } ``` So what do you think about my creation? :)