5

I have taken a look here before to see how I could load the jar into the classpath dynamically. At the time, this solution proposed worked flawlessly:

File file = ...
URL url = file.toURI().toURL();

URLClassLoader classLoader = (URLClassLoader)ClassLoader.getSystemClassLoader();
Method method = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
method.setAccessible(true);
method.invoke(classLoader, URL);

However, this wasn't possible in Java 9+, but there was a hack involving Module#addOpens which allowed the URL method to be open. For example, the code to open the module would look like this:

try {
      final Class<?> moduleClass = Class.forName("java.lang.Module");
      final Method getModuleMethod = Class.class.getMethod("getModule");
      final Method addOpensMethod = moduleClass.getMethod("addOpens", String.class, moduleClass);
      final Object urlClassLoaderModule = getModuleMethod.invoke(URLClassLoader.class);
      final Object thisModule = getModuleMethod.invoke(DependencyUtilities.class);
      addOpensMethod.invoke(
          urlClassLoaderModule, URLClassLoader.class.getPackage().getName(), thisModule);
      Logger.info(
          "User is using Java 9+, meaning Reflection Module does have to be opened. You may safely ignore this error.");
    } catch (final ClassNotFoundException
        | NoSuchMethodException
        | IllegalAccessException
        | InvocationTargetException ignored) {
      Logger.info(
          "User is using Java 8, meaning Reflection Module does NOT have to be opened. You may safely ignore this error.");
      // Java 8 doesn't have module class -- you can ignore the error.
    }

Unfortunately, Java 16 has led to changes that strictly enforce encapsulation. One of these changes included blocking illegal reflection involving the URLClassLoader#addURL method. This means that for Java 16 and above, we aren't allowed to use this trick to load the jars dynamically into the runtime.

You may ask why I am not allowed to shade the dependencies into my application. The reason due to being that restrictions force my application to fit within a certain size (2 MB). Most famously used libraries in Java will surpass this limit, especially the ones that I am using. (The jar itself must be under a certain size, but it can download dependencies to a separate folder and load them)

Another restriction includes loading it during runtime. My application isn't necessarily standalone, meaning that I lack the ability to run it with JVM Arguments. That means that I would be unable to use this as a solution.

Does anyone have some suggestions I could take?

Brandon Li
  • 63
  • 1
  • 1
  • 6

0 Answers0