0

*Getting following exception when trying to load an external Sample .jar at runtime using : Class clazz = Class.forName(jarClass);.

Exception: Module "deployment .test.war" from Service Module Loader] java.lang.ClassNotFoundException: org.abc.xyz.def.abc.Sample from [Module "deployment.test.war" from Service Module Loader]

*Have then modified the class loader from "this.getClass().getClassLoader()" to "ClassLoader.getSystemClassLoader()" but then it started throwing following exception :

deployment.test.war//org.abc.pqr.tasks.JavaDataPlayTask$1.run(JavaDataPlayTask.java:450) - Execution of Java Data Play package failed: org/abc/pqr/tasks/DataPlay java.lang.NoClassDefFoundError: org/abc/pqr/tasks/DataPlay

*The piece of code that performs dynamic class loading is inside a Main.jar *Class inside the Sample.jar implements an interface "DataPlay" that is available in Main.jar

Have tried approaches defined in the following link but none of them worked for me:

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: how to use a classloader to replace one jar library version with another at runtime

How to load classes from jar file at runtime?

Load jar dynamically at runtime?

*Is the approach mentioned in the following link is suitable? https://access.redhat.com/documentation/en-us/jboss_enterprise_application_platform/6/html/migration_guide/find_the_jboss_module_dependency1

*Is Java Platform Module System, the only solution to this problem?

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;
}

}
Hima Patel
  • 11
  • 3
  • Where does `Main.jar` live? – James R. Perkins Jun 09 '21 at 17:08
  • Main.jar resides in the lib folder (WEB-INF/lib) deployed on wildfly 15 server. Sample.jar is located at some external path on the server i.e var/data/HOME/archives/Sample.jar – Hima Patel Jun 10 '21 at 06:40
  • How do you add `Sample.jar` to your deployment? – James R. Perkins Jun 10 '21 at 14:44
  • *User uploads a zip file that can contain one or many jars. *When the zip is uploaded, the application extracts it and places all the jars at path " var/data/HOME/archives", also loads the Sample.jar or any other required jar using code (I have edited my question to add a code snippet) in addJar(jarfilePath, this.getClass().getClassLoader()) method. *At runtime when an application tries to access the class using "Class.forName(jarClass)", the exception is thrown as mention above. – Hima Patel Jun 15 '21 at 04:08
  • I'm not too sure how that design would work in a modular class loader. It would be better to modify the deployment or create a module itself with the libraries required which would require a reload of the server. This also looks highly fragile as it's relying on implementation details of a class loader that could change in any JDK release or even between vendors. – James R. Perkins Jun 15 '21 at 18:53

0 Answers0