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. 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. 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); } // 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? // Bryan