[java] How to load a jar file at runtime

I was asked to build a java system that will have the ability to load new code (expansions) while running. How do I re-load a jar file while my code is running? or how do I load a new jar?

Obviously, since constant up-time is important, I'd like to add the ability to re-load existing classes while at it (if it does not complicate things too much).

What are the things I should look out for? (think of it as two different questions - one regarding reloading classes at runtime, the other regarding adding new classes).

This question is related to java jar runtime classloader

The answer is


I googled a bit, and found this code here:

File file = getJarFileToLoadFrom();   
String lcStr = getNameOfClassToLoad();   
URL jarfile = new URL("jar", "","file:" + file.getAbsolutePath()+"!/");    
URLClassLoader cl = URLClassLoader.newInstance(new URL[] {jarfile });   
Class loadedClass = cl.loadClass(lcStr);   

Can anyone share opinions/comments/answers regarding this approach?


I was asked to build a java system that will have the ability to load new code while running

You might want to base your system on OSGi (or at least take a lot at it), which was made for exactly this situation.

Messing with classloaders is really tricky business, mostly because of how class visibility works, and you do not want to run into hard-to-debug problems later on. For example, Class.forName(), which is widely used in many libraries does not work too well on a fragmented classloader space.


This works for me:

File file  = new File("c:\\myjar.jar");

URL url = file.toURL();  
URL[] urls = new URL[]{url};

ClassLoader cl = new URLClassLoader(urls);
Class cls = cl.loadClass("com.mypackage.myclass");

Use org.openide.util.Lookup and ClassLoader to dynamically load the Jar plugin, as shown here.

public LoadEngine() {
    Lookup ocrengineLookup;
    Collection<OCREngine> ocrengines;
    Template ocrengineTemplate;
    Result ocrengineResults;
    try {
        //ocrengineLookup = Lookup.getDefault(); this only load OCREngine in classpath of  application
        ocrengineLookup = Lookups.metaInfServices(getClassLoaderForExtraModule());//this load the OCREngine in the extra module as well
        ocrengineTemplate = new Template(OCREngine.class);
        ocrengineResults = ocrengineLookup.lookup(ocrengineTemplate); 
        ocrengines = ocrengineResults.allInstances();//all OCREngines must implement the defined interface in OCREngine. Reference to guideline of implement org.openide.util.Lookup for more information

    } catch (Exception ex) {
    }
}

public ClassLoader getClassLoaderForExtraModule() throws IOException {

    List<URL> urls = new ArrayList<URL>(5);
    //foreach( filepath: external file *.JAR) with each external file *.JAR, do as follows
    File jar = new File(filepath);
    JarFile jf = new JarFile(jar);
    urls.add(jar.toURI().toURL());
    Manifest mf = jf.getManifest(); // If the jar has a class-path in it's manifest add it's entries
    if (mf
            != null) {
        String cp =
                mf.getMainAttributes().getValue("class-path");
        if (cp
                != null) {
            for (String cpe : cp.split("\\s+")) {
                File lib =
                        new File(jar.getParentFile(), cpe);
                urls.add(lib.toURI().toURL());
            }
        }
    }
    ClassLoader cl = ClassLoader.getSystemClassLoader();
    if (urls.size() > 0) {
        cl = new URLClassLoader(urls.toArray(new URL[urls.size()]), ClassLoader.getSystemClassLoader());
    }
    return cl;
}

I was asked to build a java system that will have the ability to load new code while running

You might want to base your system on OSGi (or at least take a lot at it), which was made for exactly this situation.

Messing with classloaders is really tricky business, mostly because of how class visibility works, and you do not want to run into hard-to-debug problems later on. For example, Class.forName(), which is widely used in many libraries does not work too well on a fragmented classloader space.


I googled a bit, and found this code here:

File file = getJarFileToLoadFrom();   
String lcStr = getNameOfClassToLoad();   
URL jarfile = new URL("jar", "","file:" + file.getAbsolutePath()+"!/");    
URLClassLoader cl = URLClassLoader.newInstance(new URL[] {jarfile });   
Class loadedClass = cl.loadClass(lcStr);   

Can anyone share opinions/comments/answers regarding this approach?


I was asked to build a java system that will have the ability to load new code while running

You might want to base your system on OSGi (or at least take a lot at it), which was made for exactly this situation.

Messing with classloaders is really tricky business, mostly because of how class visibility works, and you do not want to run into hard-to-debug problems later on. For example, Class.forName(), which is widely used in many libraries does not work too well on a fragmented classloader space.


This works for me:

File file  = new File("c:\\myjar.jar");

URL url = file.toURL();  
URL[] urls = new URL[]{url};

ClassLoader cl = new URLClassLoader(urls);
Class cls = cl.loadClass("com.mypackage.myclass");

I googled a bit, and found this code here:

File file = getJarFileToLoadFrom();   
String lcStr = getNameOfClassToLoad();   
URL jarfile = new URL("jar", "","file:" + file.getAbsolutePath()+"!/");    
URLClassLoader cl = URLClassLoader.newInstance(new URL[] {jarfile });   
Class loadedClass = cl.loadClass(lcStr);   

Can anyone share opinions/comments/answers regarding this approach?


Use org.openide.util.Lookup and ClassLoader to dynamically load the Jar plugin, as shown here.

public LoadEngine() {
    Lookup ocrengineLookup;
    Collection<OCREngine> ocrengines;
    Template ocrengineTemplate;
    Result ocrengineResults;
    try {
        //ocrengineLookup = Lookup.getDefault(); this only load OCREngine in classpath of  application
        ocrengineLookup = Lookups.metaInfServices(getClassLoaderForExtraModule());//this load the OCREngine in the extra module as well
        ocrengineTemplate = new Template(OCREngine.class);
        ocrengineResults = ocrengineLookup.lookup(ocrengineTemplate); 
        ocrengines = ocrengineResults.allInstances();//all OCREngines must implement the defined interface in OCREngine. Reference to guideline of implement org.openide.util.Lookup for more information

    } catch (Exception ex) {
    }
}

public ClassLoader getClassLoaderForExtraModule() throws IOException {

    List<URL> urls = new ArrayList<URL>(5);
    //foreach( filepath: external file *.JAR) with each external file *.JAR, do as follows
    File jar = new File(filepath);
    JarFile jf = new JarFile(jar);
    urls.add(jar.toURI().toURL());
    Manifest mf = jf.getManifest(); // If the jar has a class-path in it's manifest add it's entries
    if (mf
            != null) {
        String cp =
                mf.getMainAttributes().getValue("class-path");
        if (cp
                != null) {
            for (String cpe : cp.split("\\s+")) {
                File lib =
                        new File(jar.getParentFile(), cpe);
                urls.add(lib.toURI().toURL());
            }
        }
    }
    ClassLoader cl = ClassLoader.getSystemClassLoader();
    if (urls.size() > 0) {
        cl = new URLClassLoader(urls.toArray(new URL[urls.size()]), ClassLoader.getSystemClassLoader());
    }
    return cl;
}

I googled a bit, and found this code here:

File file = getJarFileToLoadFrom();   
String lcStr = getNameOfClassToLoad();   
URL jarfile = new URL("jar", "","file:" + file.getAbsolutePath()+"!/");    
URLClassLoader cl = URLClassLoader.newInstance(new URL[] {jarfile });   
Class loadedClass = cl.loadClass(lcStr);   

Can anyone share opinions/comments/answers regarding this approach?


Examples related to java

Under what circumstances can I call findViewById with an Options Menu / Action Bar item? How much should a function trust another function How to implement a simple scenario the OO way Two constructors How do I get some variable from another class in Java? this in equals method How to split a string in two and store it in a field How to do perspective fixing? String index out of range: 4 My eclipse won't open, i download the bundle pack it keeps saying error log

Examples related to jar

Running JAR file on Windows 10 Add jars to a Spark Job - spark-submit Deploying Maven project throws java.util.zip.ZipException: invalid LOC header (bad signature) java.lang.NoClassDefFoundError: com/fasterxml/jackson/core/JsonFactory Maven Error: Could not find or load main class Where can I download mysql jdbc jar from? Access restriction: The type 'Application' is not API (restriction on required library rt.jar) Create aar file in Android Studio Checking Maven Version Creating runnable JAR with Gradle

Examples related to runtime

how can I debug a jar at runtime? How to check whether java is installed on the computer Excel VBA Code: Compile Error in x64 Version ('PtrSafe' attribute required) Excel VBA Run-time error '424': Object Required when trying to copy TextBox Execute external program An unhandled exception of type 'System.IO.FileNotFoundException' occurred in Unknown Module Error when checking Java version: could not find java.dll Change the location of an object programmatically java.lang.NoClassDefFoundError: Could not initialize class XXX How permission can be checked at runtime without throwing SecurityException?

Examples related to classloader

Caused By: java.lang.NoClassDefFoundError: org/apache/log4j/Logger How to get names of classes inside a jar file? How do I put all required JAR files in a library folder inside the final JAR file with Maven? Dealing with "Xerces hell" in Java/Maven? What is the difference between Class.getResource() and ClassLoader.getResource()? How to use ClassLoader.getResources() correctly? this.getClass().getClassLoader().getResource("...") and NullPointerException Load properties file in JAR? Difference between thread's context class loader and normal classloader URL to load resources from the classpath in Java