[英]Add jar to classpath at runtime under java 9
Until java9 for adding external jar to classpath in runtime by programmatically everybody used:直到java9以编程方式将外部 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 aURLClassLoader
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 usingClass.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 Instrumentation的appendToSystemClassLoaderSearch(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.