不确定标题是否很好。不知道如何更好地描述它。在那里也全力以赴。现在到实际问题。
我正在尝试为自己制作的程序制作插件。我定义了一堆接口和抽象类。这些是在插件中实现的,然后像这样在实际程序中加载
File pluginFolder = new File(PLUGIN_PATH);
if (!pluginFolder.exists())
pluginFolder.mkdir();
File[] files = pluginFolder.listFiles((dir, name) -> name.endsWith(".jar"));
ArrayList<URL> urls = new ArrayList<>();
ArrayList<String> classes = new ArrayList<>();
if (files != null) {
Arrays.stream(files).forEach(file -> {
try {
JarFile jarFile = new JarFile(file);
urls.add(new URL(String.format("jar:file:%s/%s!/", PLUGIN_PATH, file.getName())));
jarFile.stream().forEach(jarEntry -> {
if (jarEntry.getName().endsWith(".class"))
classes.add(jarEntry.getName());
});
} catch (IOException e) {
e.printStackTrace();
}
});
URLClassLoader pluginLoader = new URLClassLoader(urls.toArray(new URL[urls.size()]));
this.apiClientList = new LinkedList<>();
classes.forEach(curClassString -> {
try {
Class curClass = pluginLoader.loadClass(curClassString.replaceAll("/", ".").replace(".class", ""));
if(curClass.getSuperclass() == ApiClient.class) {
try {
this.apiClientList.add((ApiClient) curClass.getConstructor().newInstance());
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
});
}
现在,这可以很好地返回虚拟数据(该插件应该与rest API对话,或者实际上返回电影名称,艺术品和描述的任何东西)。不过,一旦我将这3个依赖项添加到插件的maven中,就可以了
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId>
<version>2.26</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.inject</groupId>
<artifactId>jersey-hk2</artifactId>
<version>2.26</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
<version>1.1.1</version>
<scope>compile</scope>
</dependency>
它会使程序崩溃(尽管如果我向其添加主类,则该插件可以作为独立的jar正常工作)。这是我得到的异常(从终端运行带有主类的相同jar时也不例外)。
java.lang.reflect.InvocationTargetException
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:564)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:473)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:372)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:564)
at java.base/sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:941)
Caused by: java.lang.NoClassDefFoundError: javax/xml/bind/annotation/adapters/XmlAdapter
at java.base/java.lang.ClassLoader.defineClass1(Native Method)
at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1009)
at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:174)
at java.base/java.net.URLClassLoader.defineClass(URLClassLoader.java:545)
at java.base/java.net.URLClassLoader.access$100(URLClassLoader.java:83)
at java.base/java.net.URLClassLoader$1.run(URLClassLoader.java:453)
at java.base/java.net.URLClassLoader$1.run(URLClassLoader.java:447)
at java.base/java.security.AccessController.doPrivileged(Native Method)
at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:446)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:566)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:499)
at pluginapi.PluginLoader.lambda$loadPlugins$3(PluginLoader.java:63)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1378)
at pluginapi.PluginLoader.loadPlugins(PluginLoader.java:61)
at pluginapi.PluginLoader.<init>(PluginLoader.java:21)
at pluginapi.PluginLoader.instanceOf(PluginLoader.java:27)
at fxui.Main.main(Main.java:47)
... 11 more
Caused by: java.lang.ClassNotFoundException: javax.xml.bind.annotation.adapters.XmlAdapter
at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:466)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:566)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:499)
... 28 more
Exception running application fxui.Main
并非所有Maven依赖项都发生这种情况。例如,谷歌gson可以正常工作。我没有使用插件的应用程序中包含任何插件(也没有gson),我绝对不想这样做,因为那样做会破坏整个目的。
除ContractsLibrary(用于定义插件形状的Interfaces和Abstract方法)之外,所有项目都使用Java10(因为我认为jitpack,我以前将其添加为maven依赖项还不能编译Java10)。我觉得这值得一提,因为过去Java8的模块系统有时会有些奇怪。
此行if(curClass.getSuperclass() == ApiClient.class)
中引发了异常,在调试时,我发现该类实际上不再等于我正在寻找的类,但是,上一行中的类是{{ 1}}。因此,真正的问题不是平凡,而是上面的线。
我的意思是我猜这很有道理,因为我只是循环抛出了所有.class文件。那只是第一个,它碰巧在第一个.class文件中崩溃,女巫是属于球衣的一些异常。应该更具体一点,然后我可能不再明白了。
编辑:“已解决”(或根据您的看法躲避了项目符号) 我改变了
org.glassfish.jersey.client.AbortException
到
jarFile.stream().forEach(jarEntry -> {
if (jarEntry.getName().endsWith(".class")) {
classes.add(jarEntry.getName());
}
});
现在可以使用了。我的所有课程(现在还是无论如何)都放在一个名为jarFile.stream().forEach(jarEntry -> {
if (jarEntry.getName().endsWith(".class") && jarEntry.getName().startsWith("api/")) {
classes.add(jarEntry.getName());
}
});
的程序包中,因此仅给我我的课程(现在)。以后我可以做得更好,昨天还是整个晚上都以某种方式使我无法解决这个问题。现在,我可以真正尝试使用它了。 :)