我当前的java项目正在使用来自另一个项目(同一个包)的方法和变量。现在,另一个项目的jar必须在类路径中才能正常工作。我的问题是jar的名称可以并且会因为版本的增加而改变,并且因为你不能在manifest类路径中使用通配符,所以不可能将它添加到类路径中。所以目前启动我的应用程序的唯一选择是使用命令行中的-cp
参数,手动添加我的项目所依赖的另一个jar。
为了改善这一点,我想动态加载jar并阅读有关使用ClassLoader的信息。我为它阅读了很多例子,但是我仍然不明白如何在我的案例中使用它。
我想要的是加载jar文件,比方说,myDependency-2.4.1-SNAPSHOT.jar
,但它应该能够只搜索以myDependency-
开头的jar文件,因为我已经说过了版本号可以随时改变。然后我应该能够像我现在一样在我的代码中使用它的方法和变量(比如ClassInMyDependency.exampleMethod()
)。
任何人都可以帮我解决这个问题,因为我现在已经在网上搜索了几个小时,但仍然没有得到如何使用ClassLoader来做我刚刚解释过的事情。
非常感谢提前
答案 0 :(得分:9)
确实有时这是必要的。这就是我在制作中的表现。它使用反射来绕过系统类加载器中addURL
的封装。
/*
* Adds the supplied Java Archive library to java.class.path. This is benign
* if the library is already loaded.
*/
public static synchronized void loadLibrary(java.io.File jar) throws MyException
{
try {
/*We are using reflection here to circumvent encapsulation; addURL is not public*/
java.net.URLClassLoader loader = (java.net.URLClassLoader)ClassLoader.getSystemClassLoader();
java.net.URL url = jar.toURI().toURL();
/*Disallow if already loaded*/
for (java.net.URL it : java.util.Arrays.asList(loader.getURLs())){
if (it.equals(url)){
return;
}
}
java.lang.reflect.Method method = java.net.URLClassLoader.class.getDeclaredMethod("addURL", new Class[]{java.net.URL.class});
method.setAccessible(true); /*promote the method to public access*/
method.invoke(loader, new Object[]{url});
} catch (final java.lang.NoSuchMethodException |
java.lang.IllegalAccessException |
java.net.MalformedURLException |
java.lang.reflect.InvocationTargetException e){
throw new MyException(e);
}
}
答案 1 :(得分:2)
我需要在运行时为Java 8和Java 9+加载jar文件。这是执行此操作的方法(如果可能,请使用Spring Boot 1.5.2)。
public static synchronized void loadLibrary(java.io.File jar) {
try {
java.net.URL url = jar.toURI().toURL();
java.lang.reflect.Method method = java.net.URLClassLoader.class.getDeclaredMethod("addURL", new Class[]{java.net.URL.class});
method.setAccessible(true); /*promote the method to public access*/
method.invoke(Thread.currentThread().getContextClassLoader(), new Object[]{url});
} catch (Exception ex) {
throw new RuntimeException("Cannot load library from jar file '" + jar.getAbsolutePath() + "'. Reason: " + ex.getMessage());
}
}