This section explains how classes are located and loaded by the client platform.
A class loader is responsible for loading classes. A class is loaded by a hierarchy of cooperating class loaders as shown in the figure below.
Figure 1. Class loaders
A typical Java application has a global name space that consists of the contents of the JARs in a single, well-defined class path. A set of class loaders cooperates to locate and load classes based on this class path. These class loaders include the Application Class Loader to load application classes (normally found in the CLASSPATH
), the Extension Class Loader to load standard extension classes (normally in the jre/lib/ext
directory, which is specified in the java.ext.dirs
property), and the Boot Class Loader to load system classes (normally from rt.jar
in the jre/lib
Class loading functions differently in the client platform because the client platform is built on the OSGi Service Framework. Since the mechanics for supporting plug-ins are implemented by using the OSGi Service Framework, a plug-in is the same as an OSGi bundle for the purpose of this explanation. The bundle manifest specifies a bundle's prerequisite and local classpath which are used for Java class loading. The bundle manifest also may specify a bundle activator which is loaded and used for bundle lifecycle operations.
Each bundle installed and resolved in the OSGi Service Framework must have a class loader created when the first attempt is made to load a class from that bundle. This class loader, called the Bundle Class Loader, provides each bundle with its own name space to avoid name conflicts and enables package sharing with other bundles.
The Bundle Class Loader searches for classes and resources in the bundle's class path as defined by the Bundle-Classpath
header in the bundle's manifest. The Bundle Class Loader has a parent class loader as specified in the osgi.parentClassloader
property. By default, the parent class loader is the Extension Class Loader for the client platform. However, the Extension Class Loader also has a parent class loader - the Boot Class Loader. As a result, the parent of the Bundle Class Loader actually consists of the Boot Class Loader and the Extension Class Loader.
A bundle can export the classes and resources in one or more of its packages by specifying each such package name in the Export-Package
header in its manifest. The classes and resources in each exported package become part of the Public Class Space and are made available to other bundles with permission to use the package. A bundle can import one or more packages by specifying each package name in the Import-Package
header in its manifest. If the bundle has permission to import these packages, then the bundle can use the classes and resources in these packages as defined in the Public Class Space. A package can be shared based on its name and, optionally, its version. Multiple bundles can share (export) a package with the same name. Each package in the Public Class Space is unique based on its package name, exporting bundle's symbolic name, and exporting bundle's version. As a result, multiple versions of the same package can exist in the Public Class Space.
A bundle may access a package from the Public Class Space by importing the package (using Import-Package
) or requiring the bundle which exports the package (using Require-Bundle
). A bundle that imports a package must know the name of the package it needs to import and may explicitly control which bundle provides the package it actually uses by specifying additional matching attributes to select a particular exporter of a package. A bundle can explicitly use all packages exported by another bundle by specifying the required bundle in the Require-Bundle
manifest in its header. The Require-Bundle
manifest header contains a list of bundle symbolic names that need to be searched after the imports are searched but before the bundle's class path is searched.
The figure below illustrates the search order used to locate classes and resources.
Figure 2. Search order used to locate classes and resources
The OSGi Framework must adhere to the following rules for class or resource loading. When a bundle's class loader is requested to load a class or find a resource, the search must be performed in the following order:
- If the class or resource is in a java.* package, the request is delegated to the parent class loader; otherwise, the search continues with the next step. If the request is delegated to the parent class loader and the class or resource is not found, then the search terminates and the request fails.
- If the class or resource is from a package included in the boot delegation list (org.osgi.framework.bootdelegation), then the request is delegated to the parent class loader. If the class or resource is found there, the search ends.
- If the class or resource is in a package that is imported using Import-Package or was imported dynamically in a previous load, then the request is delegated to the exporting bundle's class loader; otherwise the search continues with the next step. If the request is delegated to an exporting class loader and the class or resource is not found, then the search terminates and the request fails.
- If the class or resource is in a package that is imported from one or more other bundles using Require-Bundle, the request is delegated to the class loaders of the other bundles, in the order in which they are specified in this bundle's manifest. If the class or resource is not found, then the search continues with the next step.
- The bundle's own internal bundle class path is searched. If the class or resource is not found, then the search continues with the next step.
- Each attached fragment's internal bundle class path is searched. The fragments are searched in ascending bundle ID order. If the class or resource is not found, then the search continues with the next step.
- If the class or resource is in a package that is exported by the bundle or the package is imported by the bundle (using Import-Package or Require-Bundle), then the search ends and the class or resource is not found.
- Otherwise, if the class or resource is in a package that is imported using DynamicImport-Package, then a dynamic import of the package is now attempted. An exporter must conform to any implied package constraints. If an appropriate exporter is found, a wire is established so that future loads of the package are handled in Step 3. If a dynamic wire is not established, then the request fails.
- If the dynamic import of the package is established, the request is delegated to the exporting bundle's class loader. If the request is delegated to an exporting class loader and the class or resource is not found, then the search terminates and the request fails.
- If the class or resource is still not found, and the parent class loader was not already checked in step 2, then the request will be delegated to the parent class loader. Success or failure depends upon the result from the parent class loader.
When delegating to another bundle class loader, the delegated request enters this algorithm at Step 3.
Parent topic: Application design considerations: XPD622