ServiceLoader.next, вызывающий ошибку NoClassDefFoundError
Я спрашиваю, потому что я совершенно не уверен, что поступил правильно. Я использую Eclipse для веб-проекта. Давайте назовем это WebProject (Дух) в пакете com.web.project
,
Я хочу, чтобы WebProject загружал плагины JAR во время выполнения, поэтому я подумал, что могу воспользоваться java.util.ServiceLoader
, Итак, я создал интерфейс com.web.project.WebProjectPlugin
в проекте WebProject со всеми методами, которые должны реализовывать плагины.
Затем я создал проект PluginProject, добавив 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-приложение, а не веб-проект. Итак, что я здесь делаю не так?
Я немного озадачен: как он не может найти определение класса для com.web.project.WebProjectPlugin
, так как это в том же проекте, который работает? Это как-то связано с URLClassLoader
объект я использую?
Это трассировка стека.
1 ответ
Попробуйте назначить родительский загрузчик классов вашему URLClassLoader
URLClassLoader loader = new URLClassLoader(urls, Thread.currentThread().getContextClassLoader());
WebProject ожидает определенную иерархию загрузчиков классов, поэтому, возможно, ваши классы невидимы друг для друга, если иерархия родительских / дочерних элементов установлена неправильно.