问题描述
我有一个动态加载的jar文件, 在它里面有lib /我在main(导入it.xxx.xx)中使用的另一个jar(外部库)。 如何在classpath中动态加载此外部库? 我的代码不起作用:
public static void runOne(String jar,String class_name,Optional<String> test_name,TestExecutionListener listener) throws Exception {
Launcher launcher = LauncherFactory.create();
ClassLoader loader = URLClassLoader.newInstance(
new URL[] { new File(pathJars+"/"+jar).toURI().toURL() },ServiceUtil.class.getClassLoader()
);
loader.getClass();
addURL(loader); <--here i want add a jar to classpath!
Class cls=loader.loadClass(class_name);
Constructor constructor = cls.getConstructor();
constructor.newInstance();
LauncherDiscoveryRequest request;
if (test_name.isPresent()) {
Method m = cls.getMethod(test_name.get());
request = LauncherDiscoveryRequestBuilder.request()
.selectors(selectMethod(cls,m))
.build();
}
else{
request = LauncherDiscoveryRequestBuilder.request()
.selectors(selectClass(cls))
.build();
}
TestPlan testPlan = launcher.discover(request);
launcher.registerTestExecutionListeners(listener);
launcher.execute(request);
//launcher.execute(request);
loader=null;
System.gc();
}
public static void addURL(ClassLoader loader) throws IOException {
URL u=loader.getResource("lib/sem-platform-sdk-1.0-SNAPSHOT.jar");
Class[] parameters = new Class[]{URL.class};
URLClassLoader sysloader = (URLClassLoader) ClassLoader.getSystemClassLoader();
Class sysclass = URLClassLoader.class;
try {
Method method = sysclass.getDeclaredMethod("addURL",parameters);
method.setAccessible(true);
method.invoke(sysloader,new Object[]{u});
} catch (Throwable t) {
t.printStackTrace();
throw new IOException("Error,could not add URL to system classloader");
}//end try catch
}//end method
谢谢
解决方法
通常使用构建工具(例如Maven或Gradle)完成此操作。我不知道您是否正在使用其中之一。它们使生活变得更加轻松。
我们将Maven与Apache Shade插件配合使用来实现此目的。 Maven具有自动为您设置配置的命令,然后将Shade插件添加到生成的配置文件(pom.xml)中。
https://maven.apache.org/plugins/maven-shade-plugin/index.html
,如果我正确理解了您的问题,则希望从jar文件加载的类能够访问嵌套jar文件中的类。您可以通过创建ClassLoader来实现此目的,该类加载器的jar文件的一个条目和嵌套jar文件的另一个条目。
Java有一个特殊的URL方案jar:
,用于直接引用jar条目。 (此方案和语法在the documentation of JarURLConnection中进行了描述。)因此,您可以按以下方式构造ClassLoader:
URL jarURL = new File(pathJars+"/"+jar).toURI().toURL();
URL semURL = new URL("jar:" + jarURL + "!/"
+ "lib/sem-platform-sdk-1.0-SNAPSHOT.jar");
ClassLoader loader = URLClassLoader.newInstance(
new URL[] { jarURL,semURL },ServiceUtil.class.getClassLoader()
);