Difference between revisions of "Lazy Start Bundles"

From Eclipsepedia

Jump to: navigation, search
(Requirements)
(Should I change to the new Bundle-ActivationPolicy Header?)
 
(10 intermediate revisions by 5 users not shown)
Line 1: Line 1:
 
== Overview ==
 
== Overview ==
This RFC defines a mechanism for activating bundles upon the first class request from themThis allows a system to activate bundles lazily the first time they are neededUsing this model the Framework can be started with as few active bundles as possible and only activate other bundles as new classes are loaded.
+
The Equinox team has been working with the OSGi Alliance to standardize the Eclipse Lazy Start mechanism (i.e. Eclipse-LazyStart/Eclipse-AutoStart headers)The current plan is to add a lazy activation policy to the OSGi specification for the upcoming OSGi R4.1 specificationFor more details on the current OSGi design proposal see [http://bundles.osgi.org/Design/LazyStart OSGi design]
  
== Terminology ==
+
== Why should the Eclipse Community Care ==
 +
The lazy activation policy built into the Equinox Framework is a powerful concept which allows Eclipse to launch with as few bundles active as possible.  This concept is very important to Eclipse applications for both scalability and startup performance.
  
=== Lazy Start ===
+
=== We already know that!! What has changed? ===
For the purpose of this RFC, ''lazy start'' is a life cycle policy that mandates a bundle MUST be activated upon the first request to load a class from that bundleSometimes this is referred to as auto starting because the bundle is automatically started upon first class load request.  This RFC will always use the term lazy instead of auto because auto starting can imply that a bundle is always automatically started every time the framework is launched.
+
Yeah, this is old newsWe have relied on this behavior for years.
  
=== Lazy Start Bundle ===
+
This is true, but the support for this has only been available in the Equinox OSGi Framework.  This means your bundles are tied to the Equinox Framework implementation and may not work as expected on other OSGi Framework implementations.
For the purpose of this RFC, a ''lazy start bundle'' is a bundle that has declared the lazy start life cycle policy.
+
  
=== Local Class Store ===
+
The following is a summary of what has changed in the OSGi proposal from what Equinox currently supports in version 3.2.
For the purpose of this RFC, a ''local class store'' is all classes contained in a bundle’s classpath, including classes contained in the classpaths of attached fragment bundles.
+
  
== Problem Description ==
+
==== New Bundle-ActivationPolicy Header ====
The Life Cycle Layer provides an API to control the security and life cycle operations of bundlesThis layer gives management agents the ability to install, uninstall, update, start and stop a bundleIn a typical environment a management agent will start every bundle in the framework that it thinks will be needed while the framework is running. Most bundles need to be activated for the following reasons.
+
Of course OSGi would not want to add a new header with '''Eclipse''' in the header name (e.g. Eclipse-LazyStart)A new header has been proposed Bundle-ActivationPolicySee the [http://bundles.osgi.org/Design/LazyStart OSGi design] for more details.
  
*Run some initialization code (open a port, start a thread etc.)
+
==== Found some ''bugs'' ====
*Obtain the BundleContext to participate in the service layer or register listeners with the Framework.
+
During the specification process a few ''bugs'' were found in the original lazy activation policy of Eclipse.  For example, there is a well known ClassCircularityError bug [https://bugs.eclipse.org/bugs/show_bug.cgi?id=5875 bug 5875].  This has lead to a subtle change in the way bundles are lazy activated. Consider the following example:
  
In a Framework where 1000s of bundles are installed it is not reasonable to activate every bundle upon framework launchIn a user driven application it is not possible for a management agent to know what bundles should be activated ahead of timeFor example, when a user selects a menu item in a GUI it could start a feature of the application. This feature could be implemented by a bundle that should be activated once the menu item is selected by the user.
+
A system contains three Bundles: X, Y and Z.  Bundle X has an interface x.X.  Bundle Y has a class y.Y which implements x.XBundle Z has a class z.Z which extends y.YIn this example, a request is made to load class z.Z. Class z.Z is thus the trigger class.
  
== Requirements ==
+
In Eclipse 3.2 the following occurs to lazy activate the bundles:
# Bundles MUST be allowed to specify a lazy start life cycle policy.
+
# Backwards compatibility MUST be maintained.
+
# There SHOULD NOT be any undesirable side-effects of lazy starting a bundle.  ''Unfortunately there may be undesirable side-effects in some circumstances. See section 5.4''
+
# When a bundle is activated using the lazy start policy then it MUST not be marked for persistent start.  In this case the bundle MUST not be activated when the Framework is relaunched.
+
# When a bundle is explicitly started using the Bundle.start method then it MUST be marked for persistent start even if the bundle specifies a lazy start life cycle policy.  In this case the bundle MUST be activated when the Framework is relaunched as long as it’s start-level is met.
+
# During the Framework shutdown process; bundles which were activated with the lazy start policy must not be reactivated as other bundles are stopping.
+
# During the Framework shutdown process; bundles which were activated with the lazy start policy SHOULD be shutdown in reverse dependency order.  This SHOULD help prevent bundles from loading classes from already stopped lazy start bundles.  In the case of bundle cycles the stop order is non-deterministic.
+
# During the Framework shutdown process; if an attempt to load a class from an already stopped bundle occurs and that bundle is lazy started, then a ClassNotFoundException must be thrown with an appropriate error message. TODO is a CNFE really what we want? (this is what Equinox does)  Another option may be to publish a FrameworkEvent of type ERROR and let the class load.
+
# Lazy start bundles MUST be able to participate in the service layer before the first class is loaded from the lazy start bundle.  This may require that the BundleContext for a lazy start bundle be available to component systems (e.g. Declarative Services, Spring-OSGi etc) before the bundle enters the ACTIVE state.
+
# The design of the lazy start policy MUST consider secure operations with respect to activating a bundle.
+
  
== Technical Solution ==
+
# When loading class z.Z the Framework notes that Bundle Z has a lazy activation policy.
 +
# '''Before''' searching for the class the framework activates bundle Z then proceeds to find and define class z.Z. 
 +
# When defining z.Z the class y.Y is loaded from Bundle Y. 
 +
# The Framework notes that Bundle Y has a lazy activation policy. 
 +
# '''Before''' searching for the class the framework activates bundle Y then proceeds to find and define class y.Y. 
 +
# When defining y.Y the class x.X is loaded from Bundle X. 
 +
# The Framework notes that Bundle X has a lazy activation policy.
 +
# '''Before''' searching for the class the framework activates bundle X then proceeds to find and define class x.X. 
 +
# Finally the class z.Z is returned to the client that caused it to load.  In this case the activation order was be Z, Y, X.
  
=== The Lazy Start Policy ===
+
This approach is flawed because bundles can be activated by a thread while that thread is in the process of defining a class.  There are two important reasons this must be avoided.
The lazy start policy activates bundles when the first class load request is made from a bundle’s local class store.  This policy is implemented by the Framework instead of in a management agent because only the Framework knows when the first class load request is being made.
+
  
==== Lazy Start Bundle Life Cycle ====
+
# '''Deadlock issues''' - The thread defining a class must lock the classloader while it is defining a class (when it calls ClassLoader.defineClass). A thread locking a classloader of one bundle while activating another bundle will lead to deadlocks
A lazy start bundle has the following life cycle state transitions
+
# '''ClassCircularityErrors''' - Activating a bundle while defining a class can lead to scenarios that cause the thread defining the class to request the same class be loaded again while attempting to activate the bundle.  This leads to the ClassCircularityErrors demonstrated in [https://bugs.eclipse.org/bugs/show_bug.cgi?id=5875 bug 5875].
# When a lazy start bundle’s state changes from INSTALLED to RESOLVED then it must transition into the STARTING state.  A BundleEvent of type STARTING must be fired for the lazy start bundle.  While in this state the method Bundle.getBundleContext (proposed method) must return the bundle’s BundleContext.
+
# If a lazy start bundle is stopped (by calling Bundle.stop) while in the STARTING state then the bundle state must transition to the RESOLVED state. A BundleEvent of type STOPPING must be fired, then the bundle’s state must be set to RESOLVED, finally a BundleEvent of type STOPPED must be fired for the bundle.  Upon a Framework re-launch the lazy start bundle must be allowed to enter the STARTING state again if it is still RESOLVED.
+
# If a class load request is made from the local class store of a lazy start bundle while in the STARTING state then the bundle must be activated before allowing the class to load.
+
# If the lazy start bundle fails to activate then a BundleEvent of type STOPPING must be fired, then the bundle’s state must be set to RESOLVED, finally a BundleEvent of type STOPPED must be fired for the bundle, finally a ClassNotFoundException must be thrown. ''Need to decide if we should ALWAYS throw ClassNotFoundExceptions until the bundle is refreshed to start the cycle over again or let the activation attempt happen again the next time a class load request is made.  Currently Equinox lets the activation attempt happen again and again.  But I think it is cleaner to always throw the CNFE.''
+
# If the lazy start bundle is activated successfully then the bundle’s state must be set to ACTIVE followed by a firing a BundleEvent of type STARTED, finally the class load request is allowed to continue.  The bundle must not be persistently marked for activation when the Framework is re-launched.
+
# If a class load request is made from the local class store of a lazy start bundle while in the RESOLVED state then a ClassNotFoundException must be thrown.  This implies that a class may not be loaded from a lazy start bundle if the start-level for the bundle is not met or if it failed to activate in step 4. ''Again we need to decide if this is OK. Equinox LETS classes load from bundles that are NOT at the proper start-level. This does not seem correct or consistent''
+
# If the Bundle.start method is called on a lazy start bundle, then it MUST be persistently marked for activation when the Framework is re-launched.
+
  
==== Framework Launching ====
+
The [http://bundles.osgi.org/Design/LazyStart OSGi design] for lazy activation uses the following approach to avoid these issues (using the same X, Y, Z bundles from above):
When the Framework launches the Framework’s start-level is incremented to the initial start-level. For each start-level if a lazy start bundle’s start-level is met AND it is RESOLVED then if the bundle is persistently marked for start then it transitions to the ACTIVE state; otherwise it transitions to the STARTING state.
+
  
==== Framework Shutdown ====
+
# When loading class z.Z the Framework notes that Bundle Z has a lazy activation policy
When the Framework is shutdown the Framework’s start-level is decremented to zeroFor each start-level the following steps need to be taken:
+
# Bundle Z is added to the stack of bundles that must be activated after the trigger class (z.Z) is defined. 
 +
# When defining z.Z the class y.Y is loaded from Bundle Y.
 +
# The Framework notes that Bundle Y has a lazy activation policy
 +
# Bundle Y is added to the stack of bundles that must be activated after the trigger class (z.Z) is defined. 
 +
# When defining y.Y the class x.X is loaded from Bundle X. 
 +
# The Framework notes that Bundle X has a lazy activation policy
 +
# Bundle X is added to the stack of bundles that must be activated after the trigger class (z.Z) is defined.   
 +
# Finally the class z.Z is successfully defined.
 +
# Now each bundle on the set is activated in LIFO order.  In this case the activation order would be X, Y, Z.
  
# If no lazy start bundles exist with the start-level then the bundles with the start-level are shutdown normally.
+
Notice that the order of activation has been changed from Z, Y, X to X, Y, Z.
# If at least one lazy start bundle exists with the start-level then all the bundles with the same start-level are sorted according to dependency order.  Then the bundles are shutdown ordered by dependencies such that all bundles which depend on a given bundle are shutdown before the given bundle.  In case of cycles the bundles shutdown order is not specified.
+
  
This helps prevent class load requests from lazy start bundles that have been stopped during the shutdown process.
+
== What do I need to change in my bundle ==
  
''Need more information to be filled in here.  In Equinox the lazy-start bundles are shutdown in dependency order just before the start-level of the framework starts decrementingThis causes problems if non-lazy start bundles attempt to load classes from an already stopped lazy start bundle while the non-lazy start bundles are stopping.''
+
=== Should I change to the new Bundle-ActivationPolicy Header? ===
 +
The Equinox Framework version 3.3 will continue to support the Eclipse-LazyStart and the deprecated Eclipse-AutoStart headersBundle developers that want their bundles to work across other OSGi Framework implementations should add the Bundle-ActivationPolicy header to their manifest. In most cases you can simply add the following header
  
''It is probably more consistent to shutdown the lazy start bundles with each start-level, but the lazy-start bundles within the same start-level should be shutdown in dependency order. I think we should also shutdown other non-lazy start bundles in dependency order also if there is at least one lazy start bundle at the same start-level.''
+
  Bundle-ActivationPolicy: lazy
  
=== The Bundle-StartPolicy Header ===
+
In many cases it is reasonable to also retain the old Eclipse-LazyStart or Eclipse-AutoStart headers if you need your bundle to continue to work on older versions of Eclipse.
The Bundle-StartPolicy header is introduced to allow a bundle to specify a bundle start policy.  For the purpose of this RFC only the ''lazy start'' policy is architected.  In the future other policies could be architected.  
+
  
<code>
+
==== The exceptions directive ====
Bundle-StartPolicy ::= policy-type (';' attribute)*
+
When Eclipse-LazyStart is true, the 'exceptions' attribute specifies a list of packages that '''will not''' cause the bundle to be activated when classes are loaded from them. When Eclipse-LazyStart is false, the 'exceptions' attribute specifies a list of packages that '''will''' cause the bundle to be activated when classes are loaded from them. The exception rules apply to all classes in the listed packages.
policy-type ::= token
+
attribute ::= name '=' value
+
</code>
+
  
The only defined policy type is lazy.  The lazy start policy has the following architected attributes:
+
The new Bundle-ActivationPolicy header has directives ('include' and 'exclude') that can be used to include or exclude packages in lazy activation policy. Consider the following Eclipse-LazyStart header:
* '''include''' – a string with no default value. This attribute has the following syntax:
+
  
<code>
+
Eclipse-LazyStart: true; exceptions="org.eclipse.foo1, org.eclipse.foo2"
include ::= ‘”’ package-name ( ‘,’ package-name )* ‘”’
+
</code>
+
  
A list of package names that require the lazy start policy.  If not specified then all packages require the lazy start policy
+
The example specifies that a bundle must be activated for any classes that are loaded from this bundle, except the classes in the packages 'org.eclipse.foo1' and 'org.eclipse.foo2'. The equivalent Bundle-ActivationPolicy would be the following:
* '''exclude''' – a string with no default value. This attribute has the following syntax:
+
  
<code>
+
Bundle-ActivationPolicy: lazy; exclude:="org.eclipse.foo1, org.eclipse.foo2"
exclude ::= ‘”’ package-name ( ‘,’ package-name )* ‘”’
+
</code>
+
  
A list of package names that do no use the lazy start policy.  If not specified then all packages require the lazy start policy
+
When the value of false is used for the Eclipse-LazyStart then the packages listed in the 'exceptions' attribute are the only packages that will cause a lazy activation.  Consider the following Eclipse-LazyStart header:
  
==== Alternative ====
+
Eclipse-LazyStart: false; exceptions="org.eclipse.foo1, org.eclipse.foo2"
Equinox defines the Eclipse-LazyStart header. An alternative would be to define a Bundle-LazyStart header with the following syntax:
+
  
<code>
+
The example specifies that a bundle must be activated for only classes the classes in the packages 'org.eclipse.foo1' and 'org.eclipse.foo2' that are loaded from a bundle.  The equivalent Bundle-ActivationPolicy would be the following:
Bundle-LazyStart ::= enabled (’;’ attribute)*
+
enabled ::= ‘true’ | ‘false’
+
</code>
+
  
The Bundle-LazyStart header has the following architected attributes
+
Bundle-ActivationPolicy: lazy; include:="org.eclipse.foo1, org.eclipse.foo2"
* '''exceptions''' – a string with no default value. This attribute has the following syntax:
+
  
<code>
+
=== What about the activation order changes? ===
exceptions ::= ‘”’ package-name ( ‘,’ package-name )* ‘”’
+
Yeah in the above example the activation order was changed from Z, Y, X to X, Y, Z.  That must break backwards compatibility?!!
</code>
+
  
If the lazy start policy is enabled then the exceptions attribute defines a list of package names that do not use the lazy start policyIf not enabled then the exceptions attribute defines a list of package names that do use the lazy start policy.
+
Depending on the activation order in the above example to be Z, Y, X is very brittle and unpredictable.  For example, nothing prevents another thread from accessing classes in Bundle X first causing it to be activated before Bundle Z is activated.  The contract for lazy activation is that the bundle will be activated before a client uses a class loaded from that bundleThe new design still honors this contract but it improves upon the original Eclipse design to fix the deadlock and ClassCircularityError issues.
  
If new start policies are needed then a new header would be needed to define the new policies.
+
We expect very few (if any) bundles will need to worry about this change.  Please let us know if you encounter a situation where this new approach breaks you.
  
==== Considerations ====
+
[[Category:Equinox]]
The need for defining specific packages (with include, exclude and exceptions attributes) is questionable.  Very few bundles in Equinox use such a policy.  An alternative would be to not define any architected attributes for the lazy start policy.  In this case all packages in a bundle would participate in the lazy start policy.
+
 
+
=== Security ===
+
 
+
==== Bundle.loadClass ====
+
The Bundle.loadClass method may result in activating a bundle.  The action AdminPermission.CLASS will allow the activation of lazy start bundles when Bundle.loadClass is called.
+
 
+
==== Bundle ClassLoaders ====
+
During the execution of java code additional classes get loaded, this will result in bundles being activated.  Loading classes while executing java code must not require a bundle to have the AdminPermission.EXECUTE action.
+
 
+
''If bundle classloaders are exposed (with a Bundle.getClassLoader method)  then the rights to activate a bundle will be exposed with the classloader.''
+
 
+
=== Issues ===
+
 
+
==== Class Circularity Errors ====
+
Certain scenarios will cause Class Circularity Errors to occur.  This can occur when the first class load request for a class “Foo” is made from a bundle.  This will result in the bundle being activated on the same thread which made the class load request for “Foo”.  If during the execution of the BundleActivator the class “Foo” is needed then another request to load “Foo” will occur again using the same thread.  This will result in a circularity error.
+
 
+
A workaround could be to load the first class before activating the bundle, but this has other issues if a static initializer expects the bundle to be activated.  We have tried this in Equinox and have run into other issues that ended up being worse that the circularity errors.
+
 
+
Another possible solution could be to catch the circularity error while trying to activate the bundle.  If the error is caught then allow the class to load and attempt to activate the bundle again after the class has been defined and before the class is returned from the bundle’s classloader.  In this case we should publish a FrameworkEvent.ERROR to indicate what went wrong.
+
 
+
==== Activation Dead Lock ====
+
Certain scenarios can cause threads to hang while activating a lazy start bundle.  This can occur if a lazy start bundle starts additional threads while activating.  If the bundle activator loads additional classes after it has started the threads then more than one thread could be attempting to load classes from the lazy start bundle before it has finished activating.  This can cause the threads to dead lock while waiting to start the bundle.  Eventually they will timeout while waiting for the other thread to complete the bundle activation.  Even using small timeouts will result in severe performance issues.
+
 
+
A way around this issue is to only start the threads at the very end of the lazy start bundle’s BundleActivator.start method.  This will allow the bundle to start with out causing additional classes to load after the threads have been started.
+

Latest revision as of 14:01, 5 May 2008

Contents

[edit] Overview

The Equinox team has been working with the OSGi Alliance to standardize the Eclipse Lazy Start mechanism (i.e. Eclipse-LazyStart/Eclipse-AutoStart headers). The current plan is to add a lazy activation policy to the OSGi specification for the upcoming OSGi R4.1 specification. For more details on the current OSGi design proposal see OSGi design

[edit] Why should the Eclipse Community Care

The lazy activation policy built into the Equinox Framework is a powerful concept which allows Eclipse to launch with as few bundles active as possible. This concept is very important to Eclipse applications for both scalability and startup performance.

[edit] We already know that!! What has changed?

Yeah, this is old news. We have relied on this behavior for years.

This is true, but the support for this has only been available in the Equinox OSGi Framework. This means your bundles are tied to the Equinox Framework implementation and may not work as expected on other OSGi Framework implementations.

The following is a summary of what has changed in the OSGi proposal from what Equinox currently supports in version 3.2.

[edit] New Bundle-ActivationPolicy Header

Of course OSGi would not want to add a new header with Eclipse in the header name (e.g. Eclipse-LazyStart). A new header has been proposed Bundle-ActivationPolicy. See the OSGi design for more details.

[edit] Found some bugs

During the specification process a few bugs were found in the original lazy activation policy of Eclipse. For example, there is a well known ClassCircularityError bug bug 5875. This has lead to a subtle change in the way bundles are lazy activated. Consider the following example:

A system contains three Bundles: X, Y and Z. Bundle X has an interface x.X. Bundle Y has a class y.Y which implements x.X. Bundle Z has a class z.Z which extends y.Y. In this example, a request is made to load class z.Z. Class z.Z is thus the trigger class.

In Eclipse 3.2 the following occurs to lazy activate the bundles:

  1. When loading class z.Z the Framework notes that Bundle Z has a lazy activation policy.
  2. Before searching for the class the framework activates bundle Z then proceeds to find and define class z.Z.
  3. When defining z.Z the class y.Y is loaded from Bundle Y.
  4. The Framework notes that Bundle Y has a lazy activation policy.
  5. Before searching for the class the framework activates bundle Y then proceeds to find and define class y.Y.
  6. When defining y.Y the class x.X is loaded from Bundle X.
  7. The Framework notes that Bundle X has a lazy activation policy.
  8. Before searching for the class the framework activates bundle X then proceeds to find and define class x.X.
  9. Finally the class z.Z is returned to the client that caused it to load. In this case the activation order was be Z, Y, X.

This approach is flawed because bundles can be activated by a thread while that thread is in the process of defining a class. There are two important reasons this must be avoided.

  1. Deadlock issues - The thread defining a class must lock the classloader while it is defining a class (when it calls ClassLoader.defineClass). A thread locking a classloader of one bundle while activating another bundle will lead to deadlocks
  2. ClassCircularityErrors - Activating a bundle while defining a class can lead to scenarios that cause the thread defining the class to request the same class be loaded again while attempting to activate the bundle. This leads to the ClassCircularityErrors demonstrated in bug 5875.

The OSGi design for lazy activation uses the following approach to avoid these issues (using the same X, Y, Z bundles from above):

  1. When loading class z.Z the Framework notes that Bundle Z has a lazy activation policy
  2. Bundle Z is added to the stack of bundles that must be activated after the trigger class (z.Z) is defined.
  3. When defining z.Z the class y.Y is loaded from Bundle Y.
  4. The Framework notes that Bundle Y has a lazy activation policy
  5. Bundle Y is added to the stack of bundles that must be activated after the trigger class (z.Z) is defined.
  6. When defining y.Y the class x.X is loaded from Bundle X.
  7. The Framework notes that Bundle X has a lazy activation policy
  8. Bundle X is added to the stack of bundles that must be activated after the trigger class (z.Z) is defined.
  9. Finally the class z.Z is successfully defined.
  10. Now each bundle on the set is activated in LIFO order. In this case the activation order would be X, Y, Z.

Notice that the order of activation has been changed from Z, Y, X to X, Y, Z.

[edit] What do I need to change in my bundle

[edit] Should I change to the new Bundle-ActivationPolicy Header?

The Equinox Framework version 3.3 will continue to support the Eclipse-LazyStart and the deprecated Eclipse-AutoStart headers. Bundle developers that want their bundles to work across other OSGi Framework implementations should add the Bundle-ActivationPolicy header to their manifest. In most cases you can simply add the following header

Bundle-ActivationPolicy: lazy

In many cases it is reasonable to also retain the old Eclipse-LazyStart or Eclipse-AutoStart headers if you need your bundle to continue to work on older versions of Eclipse.

[edit] The exceptions directive

When Eclipse-LazyStart is true, the 'exceptions' attribute specifies a list of packages that will not cause the bundle to be activated when classes are loaded from them. When Eclipse-LazyStart is false, the 'exceptions' attribute specifies a list of packages that will cause the bundle to be activated when classes are loaded from them. The exception rules apply to all classes in the listed packages.

The new Bundle-ActivationPolicy header has directives ('include' and 'exclude') that can be used to include or exclude packages in lazy activation policy. Consider the following Eclipse-LazyStart header:

Eclipse-LazyStart: true; exceptions="org.eclipse.foo1, org.eclipse.foo2"

The example specifies that a bundle must be activated for any classes that are loaded from this bundle, except the classes in the packages 'org.eclipse.foo1' and 'org.eclipse.foo2'. The equivalent Bundle-ActivationPolicy would be the following:

Bundle-ActivationPolicy: lazy; exclude:="org.eclipse.foo1, org.eclipse.foo2"

When the value of false is used for the Eclipse-LazyStart then the packages listed in the 'exceptions' attribute are the only packages that will cause a lazy activation. Consider the following Eclipse-LazyStart header:

Eclipse-LazyStart: false; exceptions="org.eclipse.foo1, org.eclipse.foo2"

The example specifies that a bundle must be activated for only classes the classes in the packages 'org.eclipse.foo1' and 'org.eclipse.foo2' that are loaded from a bundle. The equivalent Bundle-ActivationPolicy would be the following:

Bundle-ActivationPolicy: lazy; include:="org.eclipse.foo1, org.eclipse.foo2"

[edit] What about the activation order changes?

Yeah in the above example the activation order was changed from Z, Y, X to X, Y, Z. That must break backwards compatibility?!!

Depending on the activation order in the above example to be Z, Y, X is very brittle and unpredictable. For example, nothing prevents another thread from accessing classes in Bundle X first causing it to be activated before Bundle Z is activated. The contract for lazy activation is that the bundle will be activated before a client uses a class loaded from that bundle. The new design still honors this contract but it improves upon the original Eclipse design to fix the deadlock and ClassCircularityError issues.

We expect very few (if any) bundles will need to worry about this change. Please let us know if you encounter a situation where this new approach breaks you.