我试图使用带有urlclassloader的java serviceloader从某个jar文件加载插件,但我似乎无法让它找到我的插件类。构建这两个模块都是可行的,但是每当我运行下面的代码时,就会得到一个 java.util.NoSuchElementException
,即使文件路径是正确的,我也看不出哪里出了问题
我必须在我的intellij项目,测试(应用程序加载插件,还提供服务提供商)和pluginest(插件加载)模块。
这是测试模块结构的截图:
下面是pluginest模块的结构截图:
以下是serviceprovider插件提供程序:
package net.lbflabs;
public abstract class PluginProvider {
public abstract String getSecretMessage(int message);
}
这是扩展此类的插件:
package net.lbflabs.plugins;
import net.lbflabs.PluginProvider;
public class PluginClass extends PluginProvider {
@Override
public String getSecretMessage(int message) {
return "Here is my secret.";
}
}
下面是加载插件的主类:
package net.lbflabs;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ServiceLoader;
public class Main {
private static String path = "C:/Users/jacke/IdeaProjects/Tests/out/artifacts/PluginTest_jar/PluginTest.jar";
public static void main(String[] args) throws MalformedURLException {
System.out.println("Initializing... \nPreparing to load JAR from Path " + path + "...");
File file = new File(path);
System.out.println(file.exists()); //Prints true, so file does exist
URLClassLoader c = new URLClassLoader((new URL[]{file.getAbsoluteFile().toURI().toURL()}));
ServiceLoader<PluginProvider> loader = ServiceLoader.load(PluginProvider.class, c);
PluginProvider p = loader.iterator().next(); // Throws the java.util.NoSuchElementException
System.out.println("Secret message in plugin: " + p.getSecretMessage(1));
}
}
以下是运行测试模块时的输出:
"C:\Program Files\Java\jdk-14.0.1\bin\java.exe" "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2020.3\lib\idea_rt.jar=50330:C:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2020.3\bin" -Dfile.encoding=UTF-8 -classpath C:\Users\jacke\IdeaProjects\Tests\out\production\Tests net.lbflabs.Main
Initializing...
Preparing to load JAR from Path C:/Users/jacke/IdeaProjects/Tests/out/artifacts/PluginTest_jar/PluginTest.jar...
true
Exception in thread "main" java.util.NoSuchElementException
at java.base/java.util.ServiceLoader$2.next(ServiceLoader.java:1310)
at java.base/java.util.ServiceLoader$2.next(ServiceLoader.java:1298)
at java.base/java.util.ServiceLoader$3.next(ServiceLoader.java:1396)
at net.lbflabs.Main.main(Main.java:19)
Process finished with exit code 1
我认为pluginest模块中的服务文件的名称是正确的( net.lbflabs.PluginProvider
)并包含有效的类名( net.lbflabs.plugins.PluginClass
). 如果它是不正确的,intellij可能会发现这个问题,因为当我输入一个拼写错误时,我会得到警告。
如果有人需要它,我可以提供整个项目作为.rar(请告诉我你希望我如何分享它,例如,我创建一个onedrive链接)
ps:我已经在这里问过这个问题了,但是因为我正在做一个更大的项目,并且犹豫是否要共享其中的所有代码(而且因为我得到的唯一答案不起作用,可能是因为我没有足够的信息),我想用一个最小可行的例子来重新发布这个问题,抛出同样的异常,我希望这是好的。
1条答案
按热度按时间ikfrs5lh1#
我注意到的一点是,您构造了一个只包含1个类的类加载器。这样,它就无法创建正确的类层次结构,很可能会失败。而是通过电流
Classloader
作为你父母URLClassLoader
.现在应该能够构建一个适当的层次结构。
另一件事是在你的项目结构中
META-INF
目录不在src
包含项目源的目录。也就是说intellij会把它们放在jar外面。因此,您基本上是在添加一个没有正确文件的jar。它只包含类而不包含META-INF/services/net.lbflabs.PluginProvider
.