在java 9

时间:2017-12-31 10:38:55

标签: java jar classpath java-9 urlclassloader

直到用于通过编程方式在运行时将外部jar添加到类路径:

URLClassLoader sysloader = (URLClassLoader) ClassLoader.getSystemClassLoader();
Method method = URLClassLoader.class.getDeclaredMethod("addURL", new Class[]{URL.class});
method.invoke(sysloader, new Object[]{file.toURI().toURL()});

现在使用java9我们遇到了问题:

  

线程“main”中的异常java.lang.ClassCastException:       java.base / jdk.internal.loader.ClassLoaders $ AppClassLoader       无法转换为java.base / java.net.URLClassLoader

URLClassLoader在Java 9中不再起作用。现在在jdk9下如何以编程方式在运行时向类路径添加外部jar?

2 个答案:

答案 0 :(得分:7)

JavaSE9 release notes读到的内容相同:

  

应用程序类加载器不再是实例   ATG(一个从未实现的实现细节   在以前的版本中指定)。

     

假设的代码   ClassLoader::getSytemClassLoader会返回java.net.URLClassLoader个对象   需要更新。

     

请注意, Java SE和JDK不提供   用于动态扩充类的应用程序或库的API   运行时的路径

此外,当需要扩展类路径时,可以使用

URLClassLoader

正如thread from Oracle中所述。这有警告:

  
      
  • Class<?> clazz = Class.forName("nameofclass", true, new URLClassLoader(urlarrayofextrajarsordirs)); 使用线程的ClassLoader上下文Thread.currentThread()。setContextClassLoader(specialloader);

  •   
  • java.util.ServiceLoader确实尊重调用类'ClassLoader,而不是Thread的ClassLoader。直接创建驱动程序   使用java.sql.DriverManager

  •   
  • Class.forName("drivername", true, new URLClassLoader(urlarrayofextrajarsordirs).newInstance();使用线程的ClassLoader上下文(对javax.mail很重要)。

  •   

答案 1 :(得分:0)

纳曼的答案不能替代您所寻找的东西。 在Java 9及更高版本中,将jar添加到类路径的正确方法是使用Java InstrumentationappendToSystemClassLoaderSearch(JarFile jarfile)方法。

首先,您需要将Agent类添加到MANIFEST.MF

Launcher-Agent-Class: com.yourpackage.Agent

然后添加您的代理。 下面的示例将允许您调用Agent.addClassPath(File f)在Java 8和9+中将Jar添加到类路径中

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

}