Как динамически загрузить класс Jar в Wildfly 15

* Получение следующего исключения при попытке загрузить внешний образец .jar во время выполнения с использованием: Class clazz = Class.forName(jarClass);.

Исключение: развертывание модуля .test.war из загрузчика служебных модулей] java.lang.ClassNotFoundException: org.abc.xyz.def.abc.Sample из [развертывание модуля.test.war из загрузчика служебных модулей]

* Затем изменили загрузчик классов с this.getClass().getClassLoader() на ClassLoader.getSystemClassLoader(), но затем он начал выдавать следующее исключение:

deployment.test.war//org.abc.pqr.tasks.JavaDataPlayTask$1.run(JavaDataPlayTask.java:450) — Ошибка выполнения пакета Java Data Play: org/abc/pqr/tasks/DataPlay java.lang.NoClassDefFoundError: org/abc/pqr/задачи/DataPlay

* Фрагмент кода, выполняющий динамическую загрузку классов, находится внутри Main.jar * Класс внутри Sample.jar реализует интерфейс DataPlay, доступный в Main.jar

Пробовали подходы, определенные в следующей ссылке, но ни один из них не работал у меня:

https://access.redhat.com/documentation/en-us/jboss_enterprise_application_platform/6.2/html/development_guide/sect-use_the_class_loader_programmatically_in_a_deployment

https://kostenko.org/blog/2019/06/runtime-class-loading.html

https://www.programmersought.com/article/99402552966/

https://coderanch.com/t/614007/java/Dynamic-loading-class-external-jar

https://www.programmersought.com/article/37026364495/

Jar hell : как использовать загрузчик классов для замены одной версии библиотеки jar на другую во время выполнения

Как загрузить классы из файла jar во время выполнения?

Загружать jar динамически во время выполнения?

* Подходит ли подход, упомянутый в следующей ссылке? https://access.redhat.com/documentation/en-us/jboss_enterprise_application_platform/6/html/migration_guide/find_the_jboss_module_dependency1

* Является ли Java Platform Module System единственным решением этой проблемы?

public class ClassPathHacker {
private static Logger log = Logger.getLogger(ClassPathHacker.class);

private static final Class[] parameters = new Class[] { URL.class };

public static void addFile(String s) throws IOException {
    File f = new File(s);
    addFile(f);
}// end method

public static void addFile(File f) throws IOException {
    addURL(f.toURL());
}// end method

public static void addURL(URL u) throws IOException {

    log.debug("Loading jar file: "+u);
    
    try {
        doClasssLoading(ClassLoader.getSystemClassLoader(), u);
    } catch (Throwable t) {
        log.debug("Error, could not add URL to system classloader");
        throw new IOException(
                "Error, could not add URL to system classloader");
    }// end try catch

}// end method

public static void addJar(String jarPath, ClassLoader classLoader) throws IOException {
    File f = new File(jarPath);
    URL u = f.toURL();
    log.debug("Class loader class: "+classLoader.getClass());
    log.debug("Loading jar file: "+u);
    
    log.debug("System class loader class: "+ClassLoader.getSystemClassLoader().getClass());

    try {
        doClasssLoading(classLoader, u);
    } catch (Throwable t) {
        // t.printStackTrace();
        log.debug("Error, could not add URL to system classloader");
        throw new IOException(
                "Error, could not add URL to system classloader");
    }// end try catch
}

private static void doClasssLoading(ClassLoader classLoader, URL url) {
    if (classLoader instanceof URLClassLoader) {
        log.info("Type of URL ClassLoader");
        URLClassLoader sysloader = (URLClassLoader)classLoader;
        Class sysclass = URLClassLoader.class;
        try {
            Method method = sysclass.getDeclaredMethod("addURL", new Class[] { URL.class });
            method.setAccessible(true);
            method.invoke(sysloader, new Object[] { url });
        } catch (Exception var5) {
            var5.printStackTrace();
            throw new IllegalStateException(var5.getMessage(), var5);
        } 
    } else {
        log.info("Not of type of URL ClassLoader");
        try {
            Field field = classLoader.getClass().getDeclaredField("ucp");
            field.setAccessible(true);
            Object ucp = field.get(classLoader);
        
            Method method = ucp.getClass().getDeclaredMethod("addURL", new Class[] { URL.class });
            method.setAccessible(true);
            method.invoke(ucp, new Object[] { url });
        } catch (Exception exception) {
            exception.printStackTrace();
            throw new IllegalStateException(exception.getMessage(), exception);
        } 
    } 
}
  
public static String getMainClass(String jarPath) throws IOException {
    JarFile jarFile = new JarFile(new File(jarPath));
    Attributes attributes = jarFile.getManifest().getMainAttributes();
    String className = attributes.getValue("Main-Class");
    return className;
}

}

person Hima Patel    schedule 08.06.2021    source источник
comment
Где живет Main.jar?   -  person James R. Perkins    schedule 09.06.2021
comment
Main.jar находится в папке lib (WEB-INF/lib), развернутой на сервере wildfly 15. Sample.jar находится по некоторому внешнему пути на сервере, например var/data/HOME/archives/Sample.jar.   -  person Hima Patel    schedule 10.06.2021
comment
Как добавить Sample.jar в развертывание?   -  person James R. Perkins    schedule 10.06.2021
comment
* Пользователь загружает zip-файл, который может содержать один или несколько jar-файлов. * Когда zip загружен, приложение извлекает его и помещает все jar-файлы по пути var/data/HOME/archives, а также загружает Sample.jar или любой другой необходимый jar-файл с помощью кода (я отредактировал свой вопрос, добавив фрагмент кода ) в методе addJar(jarfilePath, this.getClass().getClassLoader()). * Во время выполнения, когда приложение пытается получить доступ к классу с помощью Class.forName(jarClass), возникает исключение, как указано выше.   -  person Hima Patel    schedule 15.06.2021
comment
Я не слишком уверен, как этот дизайн будет работать в модульном загрузчике классов. Было бы лучше изменить развертывание или создать сам модуль с необходимыми библиотеками, что потребует перезагрузки сервера. Это также выглядит очень хрупким, поскольку зависит от деталей реализации загрузчика классов, которые могут измениться в любом выпуске JDK или даже между поставщиками.   -  person James R. Perkins    schedule 15.06.2021