JDT Tutorial: Class Loading in a running plugin

Aus SDQ-Wiki

Class loading may be problematic when a running Eclipse plugin wants to load a class from the workspace. The class will not be found unless the class loader of the Java project (where the class to load lives) is used.

We want here to define a class loader for our Eclipse plugin that uses the project class loader to load any given class.


Find the projects declared in the workspace

First, we retrieve all the projects that live in the workspace where our plugin runs:

List<IJavaProject> javaProjects = new ArrayList<IJavaProject>();
IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
for(IProject project: projects){
 project.open(null /* IProgressMonitor */);
 IJavaProject javaProject = JavaCore.create(project);
 javaProjects.add(javaProject);
}


Which type of class loaders to use?

Since Eclipse plugins are referring to rssources as URLs, it is convenient to use URLClassLoaders to load classes from a search path of URLs.


Retrieve the class loader of a Java project

We read the class path entries of the Java project. We create the an URLClassLoader whose parent is the class loader of the project and with the class entries of the project.

String[] classPathEntries = JavaRuntime.computeDefaultRuntimeClassPath(project);
List<URL> urlList = new ArrayList<URL>();
for (int i = 0; i < classPathEntries.length; i++) {
 String entry = classPathEntries[i];
 IPath path = new Path(entry);
 URL url = url = path.toFile().toURI().toURL();
 urlList.add(url);
}
ClassLoader parentClassLoader = project.getClass().getClassLoader();
URL[] urls = (URL[]) urlList.toArray(new URL[urlList.size()]);
URLClassLoader classLoader = new URLClassLoader(urls, parentClassLoader);

All together

We create a list containing the class loaders of all the projects in the workspace.

loaders = new ArrayList<URLClassLoader>();
for(IJavaProject javaProject: javaProjects){
 loaders.add(getProjectClassLoader(javaProject));
}

and we finally define the loadClass method:

for(URLClassLoader loader: loaders){
 try {
  Class<?> clazz = loader.loadClass(fullyQualifiedName);
  return clazz;
 } catch (ClassNotFoundException e) {
 }
}

Reusing platform classes

A shortcoming of the above approach is that it reloads all Java classes on the classpath[1] – even those classes that have already been loaded into the running Eclipse platform. As a consequence, multiple identical versions of the same class are co-existing. Depending on the intended use case, this might lead to incompatibilities.

A way to reuse platform classes is demonstrated by Eclipse QVTo, which loads Java classes from the workspace as part of its blackbox mechanism. Take a look at QVTo's ProjectClassLoader.

Related Articles

Keywords: Eclipse, JDT, JDTJDT, Java, Class loading, Plugin, Tutorial
  1. Except those classes that are loadable by the parentClassLoader, which is the bundle class loader of org.eclipse.jdt.core.