Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Load jar dynamically at runtime?

My current java project is using methods and variables from another project (same package). Right now the other project's jar has to be in the classpath to work correctly. My problem here is that the name of the jar can and will change because of increasing versions, and because you cannot use wildcards in the manifest classpath, it's impossible to add it to the classpath. So currently the only option of starting my application is using the -cp argument from the command line, manually adding the other jar my project depends on.

To improve this, I wanted to load the jar dynamically and read about using the ClassLoader. I read a lot of examples for it, however I still don't understand how to use it in my case.

What I want is it to load a jar file, lets say, myDependency-2.4.1-SNAPSHOT.jar, but it should be able to just search for a jar file starting with myDependency- because as I already said the version number can change at anytime. Then I should just be able to use it's methods and variables in my Code just like I do now (like ClassInMyDependency.exampleMethod()).

Can anyone help me with this, as I've been searching the web for a few hours now and still don't get how to use the ClassLoader to do what I just explained.

Many thanks in advance

like image 248
JoelP Avatar asked Nov 28 '14 11:11

JoelP


People also ask

How to load jar dynamically in Java?

I used URLClassLoader child = new URLClassLoader (new URL[] {new URL("file://./my.jar")}, Main. class. getClassLoader()); assuming that the jar file is called my. jar and is located in the same directory.

What is URLClassLoader in Java?

This class loader is used to load classes and resources from a search path of URLs referring to both JAR files and directories. Any URL that ends with a '/' is assumed to refer to a directory. Otherwise, the URL is assumed to refer to a JAR file which will be opened as needed.


1 Answers

(Applies to Java version 8 and earlier).


Indeed this is occasionally necessary. This is how I do this in production. It uses reflection to circumvent the encapsulation of addURL in the system class loader.

/*
     * Adds the supplied Java Archive library to java.class.path. This is benign
     * if the library is already loaded.
     */
    public static synchronized void loadLibrary(java.io.File jar) throws MyException
    {
        try {
            /*We are using reflection here to circumvent encapsulation; addURL is not public*/
            java.net.URLClassLoader loader = (java.net.URLClassLoader)ClassLoader.getSystemClassLoader();
            java.net.URL url = jar.toURI().toURL();
            /*Disallow if already loaded*/
            for (java.net.URL it : java.util.Arrays.asList(loader.getURLs())){
                if (it.equals(url)){
                    return;
                }
            }
            java.lang.reflect.Method method = java.net.URLClassLoader.class.getDeclaredMethod("addURL", new Class[]{java.net.URL.class});
            method.setAccessible(true); /*promote the method to public access*/
            method.invoke(loader, new Object[]{url});
        } catch (final java.lang.NoSuchMethodException | 
            java.lang.IllegalAccessException | 
            java.net.MalformedURLException | 
            java.lang.reflect.InvocationTargetException e){
            throw new MyException(e);
        }
    }
like image 53
Bathsheba Avatar answered Sep 22 '22 19:09

Bathsheba