Activating, or starting, a bundle while you are in the middle of an Eclipse session is both tempting and scary at the same time. It offers some great possibilities and at the same time it may mess up things in your IDE.
What about installing and uninstalling jar bundles without restarting your IDE or just run your source plug-in project in the same instance of Eclipse as you code without spawning a new instance each time you do a minor change in your project. This will obviously save time and give you a tighter coupling between the source project and its running instance.
This feature – Compile and Run on Save – brings a new dynamic programming environment normally associated with interpreted languages, where each repetitive save/compile/run cycle is a smooth and fast one step user experience. The scenario is that when you save your plug-in project, the save triggers a build which then automatically triggers an update loading the new compiled source which then ultimately shows up in the current runtime instance of the plug-in in the IDE. Is this possible? Yes, but with a few limitations and some things to watch up for.
The first and most fundamental requirement is that plug-ins must be dynamic aware. This question is answered in an excellent way in Chris Aniszczyk article on dynamic aware bundles. In short this means that resources allocated on behalf of or by an activated bundle should be released when the bundle is stopped or unresolved.
The second question is whether Eclipse itself as an IDE is ready for dynamic bundles. How does Eclipse behave when bundles are activated and deactivated during a session?
These two questions are the topics of the rest of this blog. A bundle manager plug-in called InPlace Activator is provided (which can be downloaded at the end of this blog) to gain some experience, using dynamics in Eclipse. Despite the garbage collection problem and some other challenges in Eclipse, the future seems to be dynamic for plug-ins and bundles.
A Dynamic Component Model
The OSGi framework specification forms the basis of the Eclipse runtime. OSGi is a module system that implements a dynamic component model. Bundles can be installed, resolved, started, stopped, updated and uninstalled without requiring a reboot of the framework or as in this case a restart of the IDE hosting the very same framework.
This implies that Eclipse, beyond being compliant with the OSGi framework specification, could support the dynamics of bundles from within the IDE without rebooting. For this to work both OSGi bundles and plug-ins must be dynamic aware. The Eclipse stack is, but third party plug-ins and bundles may not be. OSGi bundles should, and are more and more, implemented with dynamics in mind.
Bundles and Plug-ins
In most cases it is not necessary to distinguish between plug-ins and bundles, but we need it here to pinpoint at which layer in the Eclipse stack limitations have been identified. OSGi was designed with dynamics in mind. Eclipse implemented OSGi as part of its stack as from version 3.0 but was initially designed for static plug-ins. Static in this context means that it is assumed that plug-ins are installed and started at startup of Eclipse and stopped and uninstalled at shutdown. The following simplified figure illustrates the difference between a plug-in and a bundle.
A plug-in is always a bundle but a bundle is not always the same as a plug-in. A bundle first becomes a plug-in when it depends on the Eclipse core runtime plug-in (org.eclipse.core.runtime) and other plug-ins indirectly through the Eclipse runtime plug-in. If the bundle in addition make contributions to the workbench it also becomes dependent on the standard UI framework plug-in (org.eclipse.ui) and its derivates. A pure OSGi bundle is only dependent on the OSGi framework (and the JRE).
Limitations have been found in plug-ins that make contributions to the workbench using the command and action set extension points. No known limitations have been found when using the Eclipse core runtime or OSGi bundles.
What are the limitations?
Limitations identified so far are in the top layer and related to action sets and the command framework. Others may of course exist, and probably do, so any feedback on undiscovered bugs in this category is more than welcome.
The Eclipse stack is as mentioned dynamic aware but there are some issues concerning dynamic updates of IDE UI elements and navigation. Contexts definitions for action sets are not always updated after bundles are resolved dynamically. A workaround is implemented in the InPlace Activator for actions sets (See Bug 295662) when plug-ins using the command framework is resolved and unresolved dynamically.
There is also a problem in the menu manager in version 3.x when dynamically populating changes committed in the Customize Perspective dialog (you bring it up from the Window | Customize Perspective … menu entry) after a plug-in using the command framework has been dynamically resolved.
Lastly, if you plan to activate plug-ins that makes contributions to the workbench using extensions, version 3.7-3.8 is recommended. Plug-ins activated dynamically works as expected in version 4.x except for its lack of responsiveness to dynamic updates of the Eclipse UI. Please see Bug 405107.
A general issue in OSGi is the absence of separate object spaces to isolate bundles. For bundles that are not dynamic aware this leads to inconsistencies when bundles are stopped. The IDE or in general any platform cannot ensure that objects from a stopped bundle will no longer be referenced by active code (stale references) leading to memory retention and inconsistencies (e.g., utilization of invalid cached data) that can introduce faults in the system. The same applies to extension points which is constructed on top of OSGi with its own dynamic plugin mechanism.
Give it a try!
The InPlace Activatior plug-in is a dynamic bundle manager that allows you to activate, update and deactivate plug-ins and bundles on the fly from within the IDE. To give it a try, install the InPlace Activator plug-in and activate any of your plug-in source projects or create a new plug-in or a pure OSGi bundle from the plug-In creation wizard and activate the created project in-place. Try changing some source and build the project. The changes should then be reflected in the newly updated bundle as long as the bundle is activated.
If you work with bundles that are dependent on each other they will be activated and deactivated in dependency order to avoid stale refrences. But most important is the responsibility of the developer to avoid stale references through best coding practices.