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 ожидает определенную иерархию загрузчиков классов, поэтому, возможно, ваши классы невидимы друг для друга, если иерархия родительских / дочерних элементов установлена ​​неправильно.

Другие вопросы по тегам