简体   繁体   English

在 java 9 下在运行时将 jar 添加到类路径

[英]Add jar to classpath at runtime under java 9

Until for adding external jar to classpath in runtime by programmatically everybody used:直到以编程方式将外部 jar 添加到运行时的类路径中,每个人都使用:

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

Now with java9 we have problem:现在使用 java9 我们有问题:

Exception in thread "main" java.lang.ClassCastException: java.base/jdk.internal.loader.ClassLoaders$AppClassLoader cannot be cast to java.base/java.net.URLClassLoader线程“main”中的异常 java.lang.ClassCastException:java.base/jdk.internal.loader.ClassLoaders$AppClassLoader 无法转换为 java.base/java.net.URLClassLoader

URLClassLoader doesn't work anymore in Java 9. What to do now under jdk9 for adding an external jar to the classpath in runtime programmatically? URLClassLoader在 Java 9 中不再工作。现在在 jdk9 下如何以编程方式在运行时将外部 jar 添加到类路径?

The JavaSE9 release notes read about the same : JavaSE9 发行说明阅读了大致相同的内容:

The application class loader is no longer an instance of java.net.URLClassLoader (an implementation detail that was never specified in previous releases).应用程序类加载器不再是java.net.URLClassLoader的实例(以前版本中从未指定的实现细节)。

Code that assumes that ClassLoader::getSytemClassLoader returns a URLClassLoader object will need to be updated.假设ClassLoader::getSytemClassLoader返回URLClassLoader对象的代码需要更新。

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 .请注意, Java SE 和 JDK 没有为应用程序或库提供 API 以在运行时动态扩充类路径

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 .正如Oracle 的这个线程中所建议的那样。 This comes with caveats:这带有警告:

  • java.util.ServiceLoader uses the thread's ClassLoader context Thread.currentThread().setContextClassLoader(specialloader); java.util.ServiceLoader使用线程的 ClassLoader 上下文 Thread.currentThread().setContextClassLoader(specialloader);

  • java.sql.DriverManager does honors the calling class' ClassLoader, -not- the Thread's ClassLoader. java.sql.DriverManager确实尊重调用类的 ClassLoader,而不是线程的 ClassLoader。 Create Driver directly using Class.forName("drivername", true, new URLClassLoader(urlarrayofextrajarsordirs).newInstance();直接使用Class.forName("drivername", true, new URLClassLoader(urlarrayofextrajarsordirs).newInstance();创建驱动程序

  • javax.activation uses the thread's ClassLoader context (important for javax.mail). javax.activation使用线程的 ClassLoader 上下文(对于 javax.mail 很重要)。

可以在这里找到正确的解决方案: https : //cgjennings.ca/articles/java-9-dynamic-jar-loading.html ...并且它可以工作。

Naman's answer is not a correct replacement for what you are looking for. Naman 的答案不是您正在寻找的正确替代品。 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.在 Java 9 及更高版本中将 jar 添加到类路径的正确方法是使用Java InstrumentationappendToSystemClassLoaderSearch(JarFile jarfile)方法。

First you will need to add your Agent class to your MANIFEST.MF首先,您需要将您的代理类添加到您的 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+下面的示例将允许您调用Agent.addClassPath(File f)将 Jar 添加到 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(); }
    }

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM