我问,因为我完全不确定我做了正确的事。我正在使用Eclipse进行Web项目。我们在包com.web.project
中将其称为WebProject(duh)。
我希望WebProject在运行时加载JAR插件,所以我想我可以利用java.util.ServiceLoader
。所以我在WebProject项目中创建了一个接口com.web.project.WebProjectPlugin
,其中包含了插件必须实现的所有方法。
然后我创建了项目PluginProject,在其Build路径中将WebProbject / build / classes添加为类文件夹:
package com.web.project.plugin;
import com.web.project.WebProjectPlugin;
public class TestPlugin implements WebProjectPlugin {
// Implementation of the interface methods...
}
然后我在插件项目中创建了一个META-INF / services文件夹,将文本文件com.web.project.WebProjectPlugin
放在里面,包含唯一的行“com.web.project.plugin.TestPlugin”。
我导出了JAR文件,检出了添加的build / classes文件夹并将其放在硬盘中的某个位置。当WebProject启动时,它会执行以下操作:
File[] jlist = pluginsDir.listFiles(new FileFilter() {
public boolean accept(File file) {
return file.getPath().toLowerCase().endsWith(".jar");
}
});
URL[] urls = new URL[jlist.length];
for (int i = 0; i < jlist.length; i++)
urls[i] = jlist[i].toURI().toURL();
URLClassLoader ucl = new URLClassLoader(urls);
ServiceLoader<WebProjectPlugin> srvl =
ServiceLoader.load(WebProjectPlugin.class, ucl);
Iterator<WebProjectPlugin> iter = srvl.iterator();
while (iter.hasNext()) {
WebProjectPlugin plugin = iter.next();
plugins.add(plugin);
}
pluginsDir
是一个File
对象,指向JAR文件所在的目录。首先,似乎srvl
完成了它的工作,因为iter
不为空,但是当它达到NoClassDefFoundError
时会抛出可怕的iter.next()
。
我已经设法创建了一个插件管理器项目来测试ServiceLoader
,它运行得很好,但它是一个普通的控制台Java应用程序,而不是一个Web项目。那么,我在这里做错了什么?
我有点困惑:它怎么能不找到com.web.project.WebProjectPlugin
的类定义,因为它在同一个正在运行的项目中?是否与我正在使用的URLClassLoader
对象有关?
这是stack trace。
答案 0 :(得分:6)
尝试将父类加载器分配给URLClassLoader
URLClassLoader loader = new URLClassLoader(urls, Thread.currentThread().getContextClassLoader());
WebProject需要类加载器的某个层次结构,因此如果未正确设置父/子符号,则可能是您的类彼此不可见。