Module isolation

Glyn Normington glyn_normington at UK.IBM.COM
Fri Jun 1 05:47:53 PDT 2007


Bryan Atsatt <bryan.atsatt at ORACLE.COM> wrote on 31/05/2007 23:52:08:

> I'd like to continue this discussion separately from the
> 291/import-by-package thread :^).
>
> To recap, the spec (sections 1.2, 6.1, 6.4) talks about using separate
> Repository instances as a means to provide isolation for environments
> like EE and Applets.
>
> I believe this is an oversight--actually, a holdover from the ideas I
> put forth in the prototype, where Repository cached Module instances.
>
> But in the current design, that is no longer the case. Repositories hold
> ModuleDefinitions, not Modules, so they are not a suitable isolation
> mechanism. It is *Module* instances with their associated loaders that
> may require isolation.

Yes, I think you're right.

>
> The current design also assumes that ModuleSystems cache Module
> instances. This certainly makes more sense than Repository. However, it
> means that systems that require isolation must arrange for separate
> ModuleSystem instances. This seems quite awkward, and a poor
abstraction.
>
> So I think we need to introduce an explicit notion of an isolation
> context that:
>
> 1. Acts as a cache for Module instances.
> 2. Enables multiple instances, each forming a separate Module namespace.
> 3. Provides out-of-the box instances for bootstrap and "system" modules.
> 4. Provides a delegation model to link instances.
> 5. Provides a lookup mechanism identical to that of Repository.
>
> Any given resolution would take place within a single context. That is,
> an initial context is selected, and while existing instances can be
> retrieved from delegated contexts, *new* instances must be created in
> the initial context.

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?

>
> To enforce this model, and to simplify the api, I believe the context
> should directly expose a "resolve" convenience method (which simply
> delegates the actual implementation).
>
> Here is a strawman API, with a simple parent-first delegation model:
>
> public abstract class ModuleContext {
>
>      // Get the context used to resolve JRE modules.
>      public static ModuleContext getBootstrapContext(){...};
>
>      // Get the context used to resolve the main module.
>      public static ModuleContext getSystemContext(){...};
>
>      // Get all contexts.
>      public static List<ModuleContext> getContexts() {...};
>
>      // Add a new context.
>      public static void addContext(ModuleContext ctx) {...}
>
>      // Remove a context (error if == default).
>      public static boolean removeContext(ModuleContext ctx) {...}
>
>      // Get the parent context (null if bootstrap).
>      public ModuleContext getParentContext(){...}
>
>      // Get the name of this context.
>      public String getContextName() {...}
>
>      // Add a new Module instance to the cache. Throw an error
>      // if an existing module contains the same definition.
>      public abstract void addModule(Module module);
>
>      // Find cached Module instances. Must check parent first.
>      public abstract List<Module> findModules(Query query);
>
>      // Remove a Module.
>      public abstract boolean remove(Module module);
>
>      // Remove all Modules created from the specified definition.
>      public static void removeAll(ModuleDefinition def) {...}
>
>      // Resolve a definition.
>      public Module resolve(ModuleDefinition def) {
>          ModuleSystem ms = def.getModuleSystem();
>          return ms.resolve(def, this);
>      }

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.

>
>      // Set the context used for JRE modules.
>      static void setBootstrapContext(ModuleContext ctx){...}
>
>      // Set the context used to define the main module.
>      static void setSystemContext(ModuleContext ctx){...}
> }
>
> The JVM would create an appropriate subtype and call
> setBootstrapContext(). JRE module instances would be cached here.
>
> The launcher would create a child context and call setSystemContext().
> The main module and any of its dependencies would be resolved here.
>
> An EE/Applet (or similar) environment can create/remove/use new contexts
> as needed for application isolation. Note that the these new contexts
> need not have the system context in their parent chain. But they do need
> the bootstrap context so the code should enforce that.
>
> The resolve() method here assumes that ModuleSystem.getModule() is
> replaced by:
>
> ModuleSystem {
>     ...
>     public abstract Module resolve(ModuleDefinition def,
>                                    ModuleContext ctx);
> }
>
> The ModuleSystem is no longer required to directly cache Modules, but to
> implement the resolution algorithm using the supplied context.
>
> ModuleSystem releaseModule() and disableModuleDefinition() methods just
> use remove() and removeAll(), respectively.
>
> This class could easily be made concrete, as the implementations are
> obviously simple. Regardless, for extensibility the actual types used at
> runtime should be under the control of the JVM/JRE and those systems
> that need to create new contexts.
>
> And, we might want to tie other existing ideas in here. For example,
> ModuleContext could be the home for "default" policies:
>
>     public abstract ImportPolicy getImportPolicy();
>     public abstract ImportOverridePolicy getImportOverridePolicy();
>
> Thoughts?

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.)

>
> // Bryan

Glyn





Unless stated otherwise above:
IBM United Kingdom Limited - Registered in England and Wales with number
741598.
Registered office: PO Box 41, North Harbour, Portsmouth, Hampshire PO6 3AU





-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mail.openjdk.java.net/pipermail/jsr277-eg-observer/attachments/20070601/3268311a/attachment.html 


More information about the jsr277-eg-observer mailing list