samedi 25 juillet 2020

How can I load a jar at runtime and replace it for later use without closing it first?

public class Test
{

    int counter = 1;
    long constructedMillis = System.currentTimeMillis();

    public Test()
    {
        System.out.println("Test constructed! " + constructedMillis + " counter=" + counter);
    }

    public void methodA(String arg1)
    {
        System.out.println("Test methodA called: "+ constructedMillis + " counter=" + counter);
        new Test2();
    }
}
public class Test2
{
    public Test2()
    {
        System.out.println("Test 2 constructed");
    }
}


// another .java
    public static Class loadJar(String pathToJar, String classPkg, boolean closeClassLoader)
    {
        URL[] urls = new URL[]
        {
            new File(pathToJar).toURI().toURL()
        };
        classLoader = new URLClassLoader(urls);
        Class cls = Class.forName(classPkg, true, classLoader);
        if (closeClassLoader) classLoader.close();
        return cls;
    }

public static void main(String[] args)
{
     // example 1: it works but I cannot rebuild the jar so I can reload it for different situation as it is locked from the classLoader since I don't close it in this case.
     {
         boolean closeClassLoader = false;
         Class test = loadJar(args[0],args[1], closeClassLoader);
         Object instance = test.newInstance();
         Method method = test.getDeclaredMethod("methodA", String.class);
         method.invoke(instance, "alpha");
     }

    // example 2:
    // if I do closeClassLoader = true then I get the following exception
    // at the method.invoke(instance, "alpha");
    // because it does new Test2();

    Exception in thread "main" java.lang.reflect.InvocationTargetException
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)

}

please note, I want the loaded jar to remain functional where I use it, however I also want the after jar to be loaded as well on the same path for the later usages.

For example I want to load a jar that has some functionality and assign user commands on it. But later on I want new users that will arrive to use the next one.

any suggestions?





Aucun commentaire:

Enregistrer un commentaire