Equinox Boot Delegation
A recap of the situation
Today in Eclipse 3.2 the bundle classloader in Equinox always delegates every class/resource load to the boot class loader before using the normal OSGi delegation. This is because we set the org.osgi.framework.bootdelegation property to '*' by default.
This has been the default to support backwards compatibility. Many bundles expect to get access to all classes available from the VM boot classpath without specifying the constraint in their bundle manifest (i.e. Import-Package or Require-Bundle).
This is not a good default behavior for Eclipse for the following reasons:
- Performance - When we delegate every class load to the boot classloader we end up with tons of ClassNotFoundExceptions because we ask the boot classloader for everything even though we know the classes should come from another bundle. For example, we delegate every org.eclipse.* class. Measurements show bootdelegation is taking up to 5-7% of startup time to get to the JDK perspective.
- Isolation - Delegating every class load to boot classpath does not allow us to isolate bundles from the packages on the boot classpath. This prevents us from shipping and using our own version of the package in a bundle. See bug 29007 and bug 145585.
The proposed solution in Bug 162231 is the following:
- By default the org.osgi.framework.bootdelegation configuration property will not be set. Currently it is set to '*'.
- A new option will be added to Equinox to enable a backwards compatibility option (tentative option is osgi.compatibility.bootdelegation). This option will be enabled by default. When this option is enabled a last resort boot delegation occurs after all other steps in the OSGi delegation process have been exhausted.
The advantage of this approach is it gives us the performance improvements and isolation we want, but it provides a level of compatibility for bundles which expect access to all packages provided by the boot classpath.
We need help from PDE to flag warnings to developers that are accessing packages from the VM without specifying proper dependencies in their bundle manifests. See bug 164188.
Some bundles today include packages that are provided by the boot classpath. For example, some bundles include their own versions of javax.xml.parsers package. With org.osgi.framework.bootdelegation set to '*' these types of bundles are not actually loading classes from these packages, instead they are getting the classes provided by the boot classpath. This is probably not not the behavior developers were expecting.
With the proposed changes these types of bundles will now be able to load and use the classes they include in themselves because we will ask their classloader for the class before asking boot. This is probably more like the behavior the developer is expecting but it does add more burden to such a bundle because now we will have multiple versions of the same package available in the framework.
System Bundle reexport
Currently the org.eclipse.core.runtime bundle uses Require-Bundle to access the system bundle and reexports it (i.e. Require-Bundle: org.eclipse.osgi; visibility:=reexport). The problem with this is that the system bundle ""org.eclipse.osgi"" exports all packages available from the current VM execution environement. If a bundle uses Require-Bundle to access org.eclipse.osgi or any other bundle that reexports org.eclipse.osgi (e.g. org.eclipse.core.runtime) they will see the packages from the VM execution environment which the system bundle exports. This will prevent a bundle from exporting their own version of the classes provided by the boot classpath.
Bundles that want to provide their own version of a package that is on the boot classpath must """not""" use Require-Bundle to access the packages in org.eclipse.osgi. This implies that the """must""" use Import-Package to access the packages they need.