我正在构建一个模块化应用程序,该应用程序的核心模块中包含模板类(由用户执行),并在每次启动时从某个目录中的.jar
文件的这些类的实现中加载实现。
这些实现的加载过程如下:
Collection<Class<?>> output = Lists.newArrayList();
JarFile jarFile = new JarFile(path);
Enumeration<JarEntry> jarEntries = jarFile.entries();
URL[] urls = { new URL("jar:file:" + path + "!/") };
URLClassLoader classLoader = URLClassLoader.newInstance(urls);
while (jarEntries.hasMoreElements()) {
JarEntry jarEntry = jarEntries.nextElement();
if(jarEntry == null
|| jarEntry.isDirectory()
|| !jarEntry.getName().endsWith(".class")){
continue;
}
...
int ignoreClass = ".class".length();
String className = jarEntry.getName().substring(0,jarEntry.getName().length()-ignoreClass);
className = className.replace('/', '.');
Class implementationClass = classLoader.loadClass(className);
Class<?> outputClass = this.loadToClassPath(path, implementationClass);
output.add(outputClass);
continue;
}
private Class<?> loadToClassPath(String path, Class toLoad) throws NoSuchMethodException,
MalformedURLException,
InvocationTargetException,
IllegalAccessException,
ClassNotFoundException {
URLClassLoader loader = (URLClassLoader) KelpApplicationRepository.class.getClassLoader();
Method addURL = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
addURL.setAccessible(true);
addURL.invoke(loader, new File(path).toURI().toURL());
return loader.loadClass(toLoad.getName());
}
它可以编译,但是出现以下运行时错误:
[17:51:24 ERROR]: de/pxav/kelp/core/sidebar/version/SidebarVersionTemplate initializing Kelp v0.1-SNAPSHOT (Is it up to date?)
java.lang.NoClassDefFoundError: de/pxav/kelp/core/sidebar/version/SidebarVersionTemplate
at java.lang.ClassLoader.defineClass1(Native Method) ~[?:1.8.0_171]
at java.lang.ClassLoader.defineClass(ClassLoader.java:763) ~[?:1.8.0_171]
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) ~[?:1.8.0_171]
at java.net.URLClassLoader.defineClass(URLClassLoader.java:467) ~[?:1.8.0_171]
at java.net.URLClassLoader.access$100(URLClassLoader.java:73) ~[?:1.8.0_171]
at java.net.URLClassLoader$1.run(URLClassLoader.java:368) ~[?:1.8.0_171]
at java.net.URLClassLoader$1.run(URLClassLoader.java:362) ~[?:1.8.0_171]
at java.security.AccessController.doPrivileged(Native Method) ~[?:1.8.0_171]
at java.net.URLClassLoader.findClass(URLClassLoader.java:361) ~[?:1.8.0_171]
at java.lang.ClassLoader.loadClass(ClassLoader.java:424) ~[?:1.8.0_171]
at java.net.FactoryURLClassLoader.loadClass(URLClassLoader.java:814) ~[?:1.8.0_171]
at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[?:1.8.0_171]
at de.pxav.kelp.core.application.inject.VersionBinderModule.implementationsOf(VersionBinderModule.java:214) ~[?:?]
at de.pxav.kelp.core.application.inject.VersionBinderModule.lambda$configure$1(VersionBinderModule.java:75) ~[?:?]
at java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184) ~[?:1.8.0_171]
at java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:175) ~[?:1.8.0_171]
at java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:948) ~[?:1.8.0_171]
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481) ~[?:1.8.0_171]
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471) ~[?:1.8.0_171]
at java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151) ~[?:1.8.0_171]
at java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174) ~[?:1.8.0_171]
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[?:1.8.0_171]
at java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:418) ~[?:1.8.0_171]
at de.pxav.kelp.core.application.inject.VersionBinderModule.configure(VersionBinderModule.java:73) ~[?:?]
at com.google.inject.AbstractModule.configure(AbstractModule.java:62) ~[?:?]
at com.google.inject.spi.Elements$RecordingBinder.install(Elements.java:340) ~[?:?]
at com.google.inject.spi.Elements.getElements(Elements.java:110) ~[?:?]
at com.google.inject.internal.InjectorShell$Builder.build(InjectorShell.java:138) ~[?:?]
at com.google.inject.internal.InternalInjectorCreator.build(InternalInjectorCreator.java:104) ~[?:?]
at com.google.inject.Guice.createInjector(Guice.java:96) ~[?:?]
at com.google.inject.Guice.createInjector(Guice.java:73) ~[?:?]
at com.google.inject.Guice.createInjector(Guice.java:62) ~[?:?]
at de.pxav.kelp.core.KelpPlugin.onLoad(KelpPlugin.java:41) ~[?:?]
at org.bukkit.craftbukkit.v1_8_R3.CraftServer.loadPlugins(CraftServer.java:297) [spigot.jar:git-Spigot-db6de12-18fbb24]
at org.bukkit.craftbukkit.v1_8_R3.CraftServer.reload(CraftServer.java:739) [spigot.jar:git-Spigot-db6de12-18fbb24]
at org.bukkit.Bukkit.reload(Bukkit.java:535) [spigot.jar:git-Spigot-db6de12-18fbb24]
at org.bukkit.command.defaults.ReloadCommand.execute(ReloadCommand.java:25) [spigot.jar:git-Spigot-db6de12-18fbb24]
at org.bukkit.command.SimpleCommandMap.dispatch(SimpleCommandMap.java:141) [spigot.jar:git-Spigot-db6de12-18fbb24]
at org.bukkit.craftbukkit.v1_8_R3.CraftServer.dispatchCommand(CraftServer.java:641) [spigot.jar:git-Spigot-db6de12-18fbb24]
at org.bukkit.craftbukkit.v1_8_R3.CraftServer.dispatchServerCommand(CraftServer.java:627) [spigot.jar:git-Spigot-db6de12-18fbb24]
at net.minecraft.server.v1_8_R3.DedicatedServer.aO(DedicatedServer.java:412) [spigot.jar:git-Spigot-db6de12-18fbb24]
at net.minecraft.server.v1_8_R3.DedicatedServer.B(DedicatedServer.java:375) [spigot.jar:git-Spigot-db6de12-18fbb24]
at net.minecraft.server.v1_8_R3.MinecraftServer.A(MinecraftServer.java:654) [spigot.jar:git-Spigot-db6de12-18fbb24]
at net.minecraft.server.v1_8_R3.MinecraftServer.run(MinecraftServer.java:557) [spigot.jar:git-Spigot-db6de12-18fbb24]
at java.lang.Thread.run(Thread.java:748) [?:1.8.0_171]
Caused by: java.lang.ClassNotFoundException: de.pxav.kelp.core.sidebar.version.SidebarVersionTemplate
at java.net.URLClassLoader.findClass(URLClassLoader.java:381) ~[?:1.8.0_171]
at java.lang.ClassLoader.loadClass(ClassLoader.java:424) ~[?:1.8.0_171]
at java.net.FactoryURLClassLoader.loadClass(URLClassLoader.java:814) ~[?:1.8.0_171]
at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[?:1.8.0_171]
... 45 more
我想知道为什么,因为核心模块中存在.class
的{{1}}文件。也许与实现类中的SidebarVersionTemplate
关键字有关?默认情况下,此关键字是否在Java中加载类?
实现类:
extends
模板类:
public class SidebarVersion extends SidebarVersionTemplate {
有什么想法吗?预先感谢