<br><font size=1 face="sans-serif"><b>Bryan Atsatt <bryan.atsatt@ORACLE.COM></b></font><tt><font size=2>
wrote on 31/05/2007 23:52:08:<br>
<br>
> I'd like to continue this discussion separately from the<br>
> 291/import-by-package thread :^).<br>
> <br>
> To recap, the spec (sections 1.2, 6.1, 6.4) talks about using separate<br>
> Repository instances as a means to provide isolation for environments<br>
> like EE and Applets.<br>
> <br>
> I believe this is an oversight--actually, a holdover from the ideas
I<br>
> put forth in the prototype, where Repository cached Module instances.<br>
> <br>
> But in the current design, that is no longer the case. Repositories
hold<br>
> ModuleDefinitions, not Modules, so they are not a suitable isolation<br>
> mechanism. It is *Module* instances with their associated loaders
that<br>
> may require isolation.</font></tt>
<br>
<br><tt><font size=2>Yes, I think you're right.</font></tt>
<br><tt><font size=2><br>
> <br>
> The current design also assumes that ModuleSystems cache Module<br>
> instances. This certainly makes more sense than Repository. However,
it<br>
> means that systems that require isolation must arrange for separate<br>
> ModuleSystem instances. This seems quite awkward, and a poor abstraction.<br>
> <br>
> So I think we need to introduce an explicit notion of an isolation<br>
> context that:<br>
> <br>
> 1. Acts as a cache for Module instances.<br>
> 2. Enables multiple instances, each forming a separate Module namespace.<br>
> 3. Provides out-of-the box instances for bootstrap and "system"
modules.<br>
> 4. Provides a delegation model to link instances.<br>
> 5. Provides a lookup mechanism identical to that of Repository.<br>
> <br>
> Any given resolution would take place within a single context. That
is,<br>
> an initial context is selected, and while existing instances can be<br>
> retrieved from delegated contexts, *new* instances must be created
in<br>
> the initial context.</font></tt>
<br>
<br><tt><font size=2>This seems like a module analogue of a class loader
except that new module instances are created in the initial context, which
seems a bit peculiar. Wouldn't this mean that Java platform module instances
could get created in an application context?</font></tt>
<br><tt><font size=2><br>
> <br>
> To enforce this model, and to simplify the api, I believe the context<br>
> should directly expose a "resolve" convenience method (which
simply<br>
> delegates the actual implementation).<br>
> <br>
> Here is a strawman API, with a simple parent-first delegation model:<br>
> <br>
> public abstract class ModuleContext {<br>
> <br>
> // Get the context used to resolve JRE modules.<br>
> public static ModuleContext getBootstrapContext(){...};<br>
> <br>
> // Get the context used to resolve the main module.<br>
> public static ModuleContext getSystemContext(){...};<br>
> <br>
> // Get all contexts.<br>
> public static List<ModuleContext> getContexts()
{...};<br>
> <br>
> // Add a new context.<br>
> public static void addContext(ModuleContext ctx)
{...}<br>
> <br>
> // Remove a context (error if == default).<br>
> public static boolean removeContext(ModuleContext
ctx) {...}<br>
> <br>
> // Get the parent context (null if bootstrap).<br>
> public ModuleContext getParentContext(){...}<br>
> <br>
> // Get the name of this context.<br>
> public String getContextName() {...}<br>
> <br>
> // Add a new Module instance to the cache. Throw
an error<br>
> // if an existing module contains the same definition.<br>
> public abstract void addModule(Module module);<br>
> <br>
> // Find cached Module instances. Must check parent
first.<br>
> public abstract List<Module> findModules(Query
query);<br>
> <br>
> // Remove a Module.<br>
> public abstract boolean remove(Module module);<br>
> <br>
> // Remove all Modules created from the specified
definition.<br>
> public static void removeAll(ModuleDefinition
def) {...}<br>
> <br>
> // Resolve a definition.<br>
> public Module resolve(ModuleDefinition def) {<br>
> ModuleSystem ms = def.getModuleSystem();<br>
> return ms.resolve(def, this);<br>
> }</font></tt>
<br>
<br><tt><font size=2>Using module context as a resolution context seems
to imply that concurrent resolutions need to be serialised to avoid interference
and so some synchronisation needs adding. Or maybe the idea is to use a
module context instance per resolution, but that wouldn't fit with a module
context being a cache spanning multiple resolutions.</font></tt>
<br><tt><font size=2><br>
> <br>
> // Set the context used for JRE modules.<br>
> static void setBootstrapContext(ModuleContext
ctx){...}<br>
> <br>
> // Set the context used to define the main module.<br>
> static void setSystemContext(ModuleContext ctx){...}<br>
> }<br>
> <br>
> The JVM would create an appropriate subtype and call<br>
> setBootstrapContext(). JRE module instances would be cached here.<br>
> <br>
> The launcher would create a child context and call setSystemContext().<br>
> The main module and any of its dependencies would be resolved here.<br>
> <br>
> An EE/Applet (or similar) environment can create/remove/use new contexts<br>
> as needed for application isolation. Note that the these new contexts<br>
> need not have the system context in their parent chain. But they do
need<br>
> the bootstrap context so the code should enforce that.<br>
> <br>
> The resolve() method here assumes that ModuleSystem.getModule() is<br>
> replaced by:<br>
> <br>
> ModuleSystem {<br>
> ...<br>
> public abstract Module resolve(ModuleDefinition def,<br>
>
ModuleContext ctx);<br>
> }<br>
> <br>
> The ModuleSystem is no longer required to directly cache Modules,
but to<br>
> implement the resolution algorithm using the supplied context.<br>
> <br>
> ModuleSystem releaseModule() and disableModuleDefinition() methods
just<br>
> use remove() and removeAll(), respectively.<br>
> <br>
> This class could easily be made concrete, as the implementations are<br>
> obviously simple. Regardless, for extensibility the actual types used
at<br>
> runtime should be under the control of the JVM/JRE and those systems<br>
> that need to create new contexts.<br>
> <br>
> And, we might want to tie other existing ideas in here. For example,<br>
> ModuleContext could be the home for "default" policies:<br>
> <br>
> public abstract ImportPolicy getImportPolicy();<br>
> public abstract ImportOverridePolicy getImportOverridePolicy();<br>
> <br>
> Thoughts?</font></tt>
<br>
<br><tt><font size=2>As I've pointed out on this list before, custom import
policies have many disadvantages including making it very hard to write
management systems that can infer dependencies before modules are installed
in the module system. Moving custom import policies out of individual modules
into the repository (which came up in discussion with Stanley and Michal
at JavaOne) or module context, leaving purely declarative metadata behind
in individual modules, would solve this problem. Then the default policy
would simply be the one returned by default. (I guess the same is true
for custom import override policies, which I'm also not fond of, particularly
at the module level.)</font></tt>
<br><tt><font size=2><br>
> <br>
> // Bryan<br>
</font></tt>
<br><tt><font size=2>Glyn</font></tt><font size=3 face="sans-serif"><br>
</font>
<br><font size=3 face="sans-serif"><br>
</font>
<hr><font size=2 face="sans-serif"><br>
<i><br>
</i></font>
<p><font size=2 face="sans-serif"><i>Unless stated otherwise above:<br>
IBM United Kingdom Limited - Registered in England and Wales with number
741598. <br>
Registered office: PO Box 41, North Harbour, Portsmouth, Hampshire PO6
3AU</i></font>
<p><font size=2 face="sans-serif"><br>
</font><font size=3 face="sans-serif"><br>
</font>
<br>
<br><font size=3 face="sans-serif"><br>
</font>