Basics about OSGi Classloading
In our opinion one of the biggest improvements to OSGi comes by classloading. Just as basic as it is the more important it becomes.
This topic will present some basics of OSGi classloading – what you can do, what it implies and what’s the meaning of.
Let us start off from the ground.
The basic of java:
Every Class object contains a reference to the ClassLoader that defined it. (Javadoc ClassLoader in Java)
Load a class included in the same bundle
As simple as it is
Write an Activator and in start() get the classloader of this class
Code:
ClassLoader myClassClassLoader = Activator.class.getClassLoader();
System.out.println("ClassLoader of BasicOneActivator is " + myClassClassLoader);
Result:
ClassLoader of BasicOneActivator is
org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader@65d0e0
The result is a DefaultClassLoader. Every Bundle has its own Classloader, a DefaultClassLoader. To get the allocated Bundle of a DefaultClassLoader we can call the getDelegate() Method.
Code:
System.out.println("Delegate to: " + ((DefaultClassLoader) myClassClassLoader).getDelegate());
Result:
Delegate to: org.codescale.osgi.classloading.basic.one_1.0.0.qualifier
Load a class exported from another bundle
To get a better opinion of classloading in osgi we’re going to load a class from another bundle with the same classloader as before.
Code:
Class<?> classA = myClassClassLoader.loadClass("org.codescale.osgi.classloading.basic.two.ClassA");
ClassLoader classLoaderA = classA.getClassLoader();
((DefaultClassLoader) oneActivator.getClassLoader()).getDelegate());
Result:
ClassLoader to load "org.codescale.osgi.classloading.basic.two.ClassA" is org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader@d6d61d Delegate to: org.codescale.osgi.classloading.basic.two_1.0.0.qualifier
The outcome of this is:
1. Every bundle (and every class in there) obtains his own Classloader
2. The Classloader of a bundle will be created if one class of this bundle is required by another bundle

Image 1: Stacktrace
This binds any class of any bundle to one specific DefaultClassLoader.
Now we know that every Bundle has a DefaultClassLoader and we know that a DefaultClassLoader has a Bundle to delegate to. But what does this delegation mean?
If we take a look at the implementation of the class ‘DefaultClassLoader’ we will see that the DefaultClassLoader is only going to delegate nearly everything!
If a class needs to be loaded – he calls the ‘ClassLoaderDelegate’ (which is a ‘BundleLoader‘). If he has to find a local class – he calls the ‘ClasspathManager‘.
First we will address our attention to the ‘BundleLoader’.
The BundleLoader and his OSGi delegation model
In the Stacktrace in Image 1 we have made our first acquaintance to a ‘BundleLoader’. There he is blamed to call the creation of a DefaultClassLoader.
Also we will find the OSGi delegation model (implemented in the methods findClass(…) and findClassInternal(…)). It declares the following order to load classes:
- if startsWith “java.” delegate to parent and terminate search
- if part of the bootdelegation list then delegate to parent
- searchHooks and call preFindClass()
- search the imported packages
- search the required bundles
- search the local bundle
- attempt to find a dynamic import source; only do this if a required source was not found
- searchHooks and call postFindClass()
- do buddy policy loading
- or last resort; do class context trick to work around VM bugs
Note: The vmarg -Dosgi.classloader.singleThreadLoads=true allows only one thread to find a class by the delegation model (except step 1)
After delegating to the required part every classloading in the delegation model returns to the method findLocalClass(String name) in the DefaultClassLoader. There the call is delegated to the ClasspathManager.
The ClasspathManager and his locking mechanism
The ClasspathManager calls a BundlyEntry to read the bytes of a *.class file. And he calls (via DefaultClassLoader) the JVM to define the class. These steps need to be thread safe. And in case of that one of two locking mechanisms may be applied.
- Default: Only one thread can lock a DefaultClassLoader to define the class
- One thread locks the whole VM during defining a class (identified by the FQN) (enabled by vmarg -Dosgi.classloader.lock=classname)
This locking may become a problem (e.g. Deadlocks with Buddy-Classloading – Bug 121737 ) so stay observant.
be happy until cancelled,
Your Codescale’s
The class loading mechanism has been described nicely. I have a query related to the plug-in class loading.
Below is the description and the structure of my project and plug-ins code base.
Scenario:
———
1. A java project named ‘SampleProject’ having package ‘com.sample.action’.
2. A plug-in project named ‘SamplePluginA’ having reference of above java project’s jar file which is set as Bundle-ClassPath also.
3. A plug-in project named ‘SamplePluginB’ having reference of the exported package ‘sample.action’ from ‘SamplePluginA’ for ‘SampleProject’.
Now, at runtime execution of the plug-in ‘SamplePluginB’, the class ‘sample.action.A’ of ‘SampleProject’ is invoked which tries to load the class ‘B’ located under the ‘SamplePluginB’. While loading this class, it throws the ClassCastException because the class loaders for both the classes differs. Whereas, if ‘sample.action.A’ tries to load a class located under the ‘SampleProject’ then it succeeds.
I would like to know the way of loading classes of ‘SamplePluginB’ from a class located in ‘SampleProject’.
The quick response will be appreciated.
Thanks & Regards,
Nitu
Hi Nitu,
Do I’ve understood you right that your Plug-Ins are looking like that:
- SamplePluginA.jar
– SampleProject.jar
— sample.action.A.class
– META-INF/MANIFEST.MF
- SamplePluginB.jar
– META-INF/MANIFEST.MF
and SamplePluginB —requires—> SamplePluginA ?
How does the ‘sample.action.A’ can load the Class ‘B’ without an dependency of ‘SamplePluginA’ to ‘SamplePluginB’ (anyway this would lead to a dependency cycle)? Maybe you can give me some pice of code which is involved…
Greetings
The configuration in the respective MANIFEST.MF is done as follows:
1. MANIFEST.MF of SamplePluginA has the entry for SampleProject.jar:
Bundle-ClassPath: lib/SampleProject.jar
Export-Package: sample.action.A;x-friends:=”SamplePluginB”
2. build.properties of SamplePluginA has the entry:
bin.includes = lib/SampleProject.jar
jars.extra.classpath = lib/SampleProject.jar
3. MANIFEST.MF of SamplePluginB has the entry:
Require-Bundle: com.sample.samplepluginA;bundle-version=”1.0.0″
The Class B is the implementation of an interface that belongs to SampleProject and a Decorator is implemented which tried to load implementor classes of this interface which are registered within the chain. This chain is build by the builder class located under the SamplePluginB.
I have tried to load the Class B from the Class located under the SampleProject by the ClassLoader object obtained from the Activator class of the SamplePluginB. This approach works fine because the class will always be loaded from its class loader. But, i need a way where i dont need to pass a ClassLoader to my core class.
I would also like to know whether am i missing any configuration in the plugin.xml or have i made mistake by creating SamplePluginB as a plugin and i would have created it as a fragment?
Thanks & Regards,
Nitu
Have you thought about using the Whiteboard Pattern with OSGi Services? If you have implementations of an interface registered in the chain – then you can use the OSGi Service Registry for this as well (and for free
)
If you do not have the dependency from A to B but have to load a Class from there, you have to get anything at all (another Class, the Classloader, Bundle or BundleContext) to be able to load a Class out of this Bundle.
OK some suggestions.
1. If you register the Class B (which implements an interface from SampleProject) as a service you can use the service registry one more time to receive this Class (an ldap filter might help you (Constants.OBJECTCLASS=com.sample.B)).
2. Use the Eclipse BuddyPolicy (but with caution! it’s only a possibility if there is really no other way out).
3. Set you project ‘SamplePluginB’ up as a fragment. See my blog post to learn what a fragment will do.
You are welcome.
Good blogpost, great looking blog, added it to my favs.
Writing special classloader is good idea. The question is how to delegate classloading to the bundle-classloader? An example?
If a class will be loaded by your classloader you need to check first of all if you can load the class by the bundle-classloader. If not – do it by yourself… and throw a classnotfound if you also can not load the class… (you will get your bundle-classloader by simply ask an already loaded class ‘getClassLoader()‘)
I have one question: I wrote my own eclipse plugin and I want to dynamicly load external Class from file. How to do it with DefaultClassLoader? I know I can use URLClassLoader (system class loader) but my class use plugin’s jar so it must be the same ClassLoader.
You need to bring the class onto the classpath of your plugin. The classpath is defined in the manifest (Bundle-ClassPath).
Another possible idea could be to use an OSGi-Service or Extension-Point.
Maybe you can tell me what your meaning of “external Class from file” is. And what’s the idea behind.
Greetings
My plugin is something like dynamic wizard to generate files. I load wizard description at runtime (including classes description for this wizard), so at the begining I don’t know where this classes will be.
Maybe you can use JDT to read the required information from the class. If that is not possible you can write a special classloder to define the required binary-class from filestream and delegate classloading to the bundle-classloader.