blob: 7aef88df0201876e02aea3de32bc827a3c72dd26 [file] [log] [blame]
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>The Equinox Project - Dynamic plugins</title>
<link rel="stylesheet" title="default" href="http://eclipse.org/default_style.css" type="text/css">
</head>
<body>
<table BORDER=0 CELLSPACING=5 CELLPADDING=2 WIDTH="100%" >
<tr>
<td ALIGN=left width="60%">
<p><font class=indextop> equinox</font><br>
<font class=indexsub> dynamic plugins > managing classloaders and instances </font> </p>
</td>
<td WIDTH="40%">&nbsp; </td>
</tr>
</table>
<table border=0 cellspacing=5 cellpadding=2 width="100%" >
<tr>
<td align=LEFT valign=TOP colspan="2" bgcolor="#0080C0"><b><font color="#FFFFFF">
Discussions</font></b></td>
</tr>
</table>
Essentially, deactivating a plugin P is a two-step process. First, the registry
asks the plugin to shutdown and then it releases its class loader. The registry
keeps a soft reference on the class loader in case the plugin would be
activated again before the class loader is actually garbage collected.
The plugin shutdown is necessary for the plugin class loader to have
a chance to go away.
<p></p><p>
When shutdown, a plugin must cleanup after object references that it leaked.
Indeed, for the class loader to go away and effectively releasing JVM-level
resources, all leaked
references must be cleaned up. A leak reference is a reference from an
outside object to an inside one. An inside object is a class loaded by
the class loader of plugin P or an instance of such a class.
An outside object is an instance of a class that is not loaded by
the class loader of P.
<br>
Note: if a plugin has started background threads, these threads
are roots of persistence for the garbage collector and should
therefore be stopped. Otherwise, the class loader will not be
garbage and will not be reclaimed, defeating the deactivation process.
</p><p>
So, what does it mean to be a good-citizen plugin?
Plugins need to track cross-plugin references and be
able to clean them up. Let's discuss and categorize
cross-plugin references.
</p><p>
Between class loaders,
we have two very different categories of Java reference:
type reference and instance references. Both are a Java
reference from an object to another, but the holder of
the reference is a Class object in the type reference
case where it is not a Class object in the instance
reference.
<BR>
The reason we differentiate them is that
object references can be cut while type references
cannot---they represent dependencies between loaded classes.
So if we have at type reference from a class loaded by plugin
P to a class loaded by plugin Q, the class loader of Q
will not go away until the class loader of P does.
This means that we cannot deactivate plugin Q
until we deactivate plugin P. This is of course a transitive
process along the inversed "require" graph.
<br>
<font color="magenta">Pascal:<br>
This is not a problem because Q can not
be deactivated if P is not.<br>
Olivier: Agreed, this is what the text says.
</font>
</p><p>
From a type reference perspective, as long as
someone has such a reference, the plugin with the referenced
class cannot be deactivated. So in other words, a plugin
can only be deactivated once all plugins requiring him
(transitively) are deactivated. This is something the registry
can do, once those plugins are shutdown and should have
cleaned up their leaked object references.
</p><p>
One of the most common object reference between plugins is
a reference on an extension object. Most extension objects
are short lived... so automated garbage collection should
still work. But not all extension objects are short-lived,
such as a view or markers for example. But unfortunately,
there is no life-cycle on extension objects, so
in general, a plugin does not know if the extension objects
it created are still used or not.
<br>
For a plugin to know if it can be deactivated, it would
have to keep track of those extension objects.
</p><p>
The next common object reference between plugins is leaked
references directly to other plugins such as SWT toolbars
or menus. These references are leaked directly, not through
the plugin registry. Here, we need plugins to maintain the knowledge
of those leaked references and to be able to clean them up
when no extension objects are still in use...
</p><p>
<font color="#FF0000">
So to summarize, we need to add a life-cycle management for
extension objects. When a plugin has no active extension objects,
it could be asked to deactivate, that is, cleanup leaked
references... and stop all background threads.
This is unfortunately not very transparent and will not work
well with existing plugins.
<BR>
It will work, that is, class loaders will get collected, for
plugins not leaking object references or doing a good job
at scoping them to live extension objects. We may be fortunate.
</font>
</p><p>
So in the above scheme, plugins know when they are no
longer used (actively speaking: no active extension
objects). But we should probably not be too aggressive
regarding deactivation...
Most plugins are probably without active extensions
most of the time. So we could monitor activities on the extensions
of plugins... and if no one has asked for the creation of any extension
of a plugin in a given period of time, the registry could ask the plugin
to deactivate. If the plugin knows that it has no active extension objects, then
it can cleanup its other leaked object references.
</p><p>
At that stage, as far as the plugin is concerned, it is deactivated.
Its class loader will only go away when all class loaders holding type
references to some of its classes will go away. This will only happen
if their plugin has been deactivated or not yet activated. Here we
see that the plugin registry has to maintain this information and
not unnecessarily ask plugins to deactivate if other plugins
requiring it are not deactivated themselves.
</p><p>
This is a good start if we assume plugins designed properly and
behave correctly. This correct behavior is required on both side
of the extension mechanism... in order to track life extension
points correctly. The most widely spread mechanism to keep track
of such things is a dispose method. Second to an explicit dispose
method is reference counting. Third is proxying. All have their
pros and cons.
</p><p>
<font color="#FF0000">
Do we all agree so far?
What do we do in failure cases, where plugins do not cleanup well
after themselves? Also, depending on which mechanism is used to
keep track of live extension objects, we may have more failure
scenarii.
</font></p>
<p>&nbsp;</p>
</body>
</html>