osgiapache-felixequinoxdynamic-class-loadersembedded-osgi

how does system bundle has access to system packages?


I'm exploring how OSGI is implemented for the last couple of weeks. I know that each bundle uses its own class loader to load its classes. As part of my investigation, I understood that parent of every bundle's class loader is null i.e boot class loader.

System.out.println("ClassInBundle class is loaded by "+ClassInBundle.class.getClassLoader());
System.out.println("ClassInBundle parent class is "+ClassInBundle.class.getClassLoader().getParent());

Output for above code which is in bundle samplebundle is

ClassInBundle class is loaded by com.sample.bundle.samplebundle [34]
ClassInBundle parent class is null

and for imports in a bundle, it maintains a map of packagename=>classloader so that it can delegate requests to the correct class loader

Bundle SB = felix.getBundleContext().getBundle(0);
List<BundleWire> sbwires=SB.adapt(BundleWiring.class).getRequiredWires(null);
List<BundleWire> li=bundle.adapt(BundleWiring.class).getRequiredWires(null);
for(BundleWire i : li){
    System.out.println(i);
}

The output for the above code is

[com.sample.bundle.samplebundle [34](R 34.0)] osgi.wiring.package; (osgi.wiring.package=com.test.packag) -> [org.apache.felix.framework [0](R 0)]
[com.sample.bundle.samplebundle [34](R 34.0)] osgi.wiring.package; (&(osgi.wiring.package=org.osgi.framework)(version>=1.8.0)(!(version>=2.0.0))) -> [org.apache.felix.framework [0](R 0)]
[com.sample.bundle.samplebundle [34](R 34.0)] osgi.wiring.package; (&(osgi.wiring.package=org.osgi.framework.wiring)(version>=1.2.0)(!(version>=2.0.0))) -> [org.apache.felix.framework [0](R 0)]
[com.sample.bundle.samplebundle [34](R 34.0)] osgi.ee; (&(osgi.ee=JavaSE)(version=1.6)) -> [org.apache.felix.framework [0](R 0)]

As you can see in the first line of above output, the package com.test.packag is added as FelixConstants.FRAMEWORK_SYSTEMPACKAGES and the bundle samplebundle is wired to system bundle[0] for com.test.packag.

So, I wanted to understand how system bundle[0] can access system packages which are loaded by different class loader(App class loader). Not only that all the core classes of OSGI like Bundle, BundleActivator, Felix are also loaded by App class loader. So, I tried debugging the Felix code to understand whether the system bundle is delegating the loadClass() requests to App class loader. Unfortunately, while debugging I observed m_wiring variable of BundleWiringImpl class, I noticed that classloader of system bundle is null(which is not possible because boot class loader only loads java.* packages).

please correct my understanding if I'm wrong.

My questions here are

what is the class loader of system_bundle[0] and what is its parent class loader?

if the parent of the system_bundle class loader is not App class loader, is system bundle also maintaining the map of package=>classloader to load classes which are loaded by app class loader?

what exactly is the hierarchy of class loaders(bundle class loaders, system class loader, boot class loader, and app class loader)?

Thank you.


Solution

  • Normally the OSGi Framework (aka the System Bundle) is loaded by the application loader and therefore has visibility of everything else on the application loader, and its parents i.e. the extension loader and the boot loader.

    It actually depends on how you write your launcher. You can embed OSGi into any standard Java application simply by instantiating a FrameworkFactory and using it to launch a Framework. When you do this, the OSGi framework is just another library on the classpath and it has visibility of the same set of classes as your own code.

    You can make things as simple or as fancy as you like. For example you could embed an OSGi Framework into a Servlet deployed in a J2EE application server... in that case the system bundle will have visibility to all the types available in the Web Application, as controlled by the contents of WEB-INF. You could even embed an OSGi Framework into a bundle deployed to another OSGi Framework... OSGi inception!

    In all these cases, the Framework can choose what set of packages to export. These packages become available to be imported by bundles inside that Framework. By default the packages exported are the standard set of JavaSE packages for the relevant JavaSE version, but you can augment with additional application-level packages.