I'm working on a Eclipse plugin that needs classes which are not known at compile time. The classes get sent over the network in jar files. I would like to dynamically load those classes at runtime.
I've tried the approach listed here: http://blog.imaginea.com/making-applications-work-together-in-eclipse/
Unfortunately it doesn't have the desired effect. While the classes do get loaded, I can't use them outside the function where I loaded them. I'm guessing it has something to do with using different class loaders.
Any help is appreciated. Even if you tell me, that it is not possible, so I know I don't have to look any further.
You have selected the JRE System Library in the panel. Un-select that and you will be able to add external jars. You can click on the Classpath or Modulepath to move the control away.
JAR stands for Java Archive file. It is a platform–independent file format that allows bundling and packaging all files associated with java application, class files, audio, and image files as well. These files are needed when we run an applet program.
If you make those jars into OSGi bundles (ie, give them a MANIFEST.MF) then you can install them into the OSGi runtime dynamically.
If you add a bundle activator to your plugin, then you can store the org.osgi.framework.BundleContext and then you can do:
Bundle [] newBundle = new Bundle[] { bundleContext.install(location, newJarInputStream) };
packageAdmin.refreshPackages( newBundle );
packageAdmin.resolveBundles( newBundle);
packageAdmin
is an instance of org.osgi.service.packageAdmin.PackageAdmin which is a service you can acquire with BundleContext#getService
The new jars can be entire bundles in their own right, or they can also be bundle fragments that have your plugin as their host. If they are fragments of your bundle then the your bundle (BundleContext#getBundle()
) will need to be included in the array passed to refreshPackages and resolveBundles.
(EDIT classloading)
Class.forName
from your plugin code will only find classes in the newly installed bundles if your plugin has dependencies that will be satisfied by the new bundles once they are resolved.
Import-Package
in your plugin's manifest. In this case your plugin will need to be included in the array passed to refreshPackages
. DynamicImport-Package
statement in your plugin's manifest. Dynamic imports are resolved during class loadingAnother option is to use Bundle.loadClass
(instead of Class.forName)on the bundle objects for your newly installed bundles. This uses the new bundle's classloader so your plugin itself does not need to have a dependency on the new bundles.
I recently did this for a plugin to eclipse:
Here's the salient code
URL[] urls = new URL[]{ new URL("jar", "", "file:" + jarFile.getAbsolutePath() + "!/")};
URLClassLoader cl = URLClassLoader.newInstance(urls, this.getClass().getClassLoader());
Class<?> loadedClass = cl.loadClass("com.whatever.SomeClass");
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With