ServiceLoader.next raises NoClassDefFoundError

I ask because I'm completely not sure that I did the right thing. I am using Eclipse for a web project. Let us call it WebProject (duh) in the package com.web.project .

I want WebProject to load JAR plugins at runtime, so I thought I could use java.util.ServiceLoader . Therefore, I created the com.web.project.WebProjectPlugin interface in a WebProject project with all the methods that plugins should implement.

Then I created a PluginProject project, adding WebProbject / build / classes to my build path as a class folder:

 package com.web.project.plugin; import com.web.project.WebProjectPlugin; public class TestPlugin implements WebProjectPlugin { // Implementation of the interface methods... } 

Then I created the META-INF / services folder in the plugin project, placed the text file com.web.project.WebProjectPlugin inside, containing the only line "com.web.project.plugin.TestPlugin".

I exported the JAR file by checking the added build / classes folder and placing it somewhere on the hard drive. When WebProject starts, it performs the following actions:

 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 is a File object that points to the directory in which the JAR file is located. At first it seems that srvl is doing its job since iter not empty, but then it throws a scary NoClassDefFoundError when it reaches iter.next() .

I have already managed to create a project of the plug-in manager for testing ServiceLoader , and it works fine, but it is a simple Java console application, not a web project. So what am I doing wrong here?

I am a little puzzled: how can he not find the class definition for com.web.project.WebProjectPlugin , since he is in the same running project? Is this something related to the URLClassLoader object I'm using?

This is a stack trace .

+6
source share
1 answer

Try assigning a parent class loader to URLClassLoader

 URLClassLoader loader = new URLClassLoader(urls, Thread.currentThread().getContextClassLoader()); 

WebProject expects a specific hierarchy of class loaders, so it may be that your classes are not visible to each other if the parent / child hierarchy is not set up properly.

+5
source

Source: https://habr.com/ru/post/943943/


All Articles