Add jar to classpath at runtime under java 9

前端 未结 2 824
北荒
北荒 2020-11-30 12:48

Until java9 for adding external jar to classpath in runtime by programmatically everybody used:

URLClassLoader sysloader = (URLClassLoader) ClassLoader.getSy         


        
相关标签:
2条回答
  • 2020-11-30 12:57

    The JavaSE9 release notes read about the same :

    The application class loader is no longer an instance of java.net.URLClassLoader (an implementation detail that was never specified in previous releases).

    Code that assumes that ClassLoader::getSytemClassLoader returns a URLClassLoader object will need to be updated.

    Note that Java SE and the JDK do not provide an API for applications or libraries to dynamically augment the class path at run-time.

    Additionally when an extended classpath is required, one can make use of

    Class<?> clazz = Class.forName("nameofclass", true, new URLClassLoader(urlarrayofextrajarsordirs));
    

    as suggested in this thread from Oracle. This comes with caveats:

    • java.util.ServiceLoader uses the thread's ClassLoader context Thread.currentThread().setContextClassLoader(specialloader);

    • java.sql.DriverManager does honors the calling class' ClassLoader, -not- the Thread's ClassLoader. Create Driver directly using Class.forName("drivername", true, new URLClassLoader(urlarrayofextrajarsordirs).newInstance();

    • javax.activation uses the thread's ClassLoader context (important for javax.mail).

    0 讨论(0)
  • 2020-11-30 13:04

    Naman's answer is not a correct replacement for what you are looking for. The correct way to add a jar to the classpath in Java 9 and above is to use Java Instrumentation's appendToSystemClassLoaderSearch(JarFile jarfile) method.

    First you will need to add your Agent class to your MANIFEST.MF

    Launcher-Agent-Class: com.yourpackage.Agent

    Then add your agent. The example below will allow you to call Agent.addClassPath(File f) to add a Jar to the classpath in both Java 8 & 9+

    public class Agent {
        private static Instrumentation inst = null;
    
        // The JRE will call method before launching your main()
        public static void agentmain(final String a, final Instrumentation inst) {
            Agent.inst = inst;
        }
    
        public static boolean addClassPath(File f) {
            ClassLoader cl = ClassLoader.getSystemClassLoader();
    
            try {
                // If Java 9 or higher use Instrumentation
                if (!(cl instanceof URLClassLoader)) {
                    inst.appendToSystemClassLoaderSearch(new JarFile(f));
                    return;
                }
    
                // If Java 8 or below fallback to old method
                Method m = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
                m.setAccessible(true);
                m.invoke(cl, (Object)f.toURI().toURL());
            } catch (Throwable e) { e.printStackTrace(); }
        }
    
    }
    
    0 讨论(0)
提交回复
热议问题