Stanley M. Ho wrote:
Hi Bryan,

Bryan Atsatt wrote:

Can you please explain the use case for releaseModule()?

If a repository instance is long-lived, the instantiated module
instances from the module definitions in the repository would be cached
for a long period of time; calling releaseModule() could help freeing up
resources when necessary, without requiring the repository instance to
be shutdown. This is also a use case from NetBeans.

Sorry, but this is just a bit fuzzy to me. I suspect that a concrete use
case is an application server, when it has stopped an application,
*could* release any modules used by that application.

But this approach doesn't really work very well. What happens when,
moments after releasing a module, another application is deployed that
needs the same module? It gets a different instance. And that could
easily lead to ClassCastExceptions and/or LinkageErrors.

How is it possible to know when it is safe to "free up resources"?

I don't think you can have it both ways. Either classes are shared for
the lifetime of the process, or they are shared *only* within a well
bounded scope. Not both.

To me, this is exactly why we need an isolation model: to provide a well
defined scope whose lifecycle can be correctly managed.



Also, when a module definition is reloaded/uninstalled, or when the
repository is shutdown, we will disable the module definitions in the
repository from the module system so any existing module instance would
be released and no new module instance can be instantiated. However,
releasing the module instance alone is not sufficient because that
module instance may be referenced by some importers. Hence, we want to
call releaseModule() on the importers as well for these module instances
to eventually become unreachable and be GCed.

Would you agree that if we did not support releaseModule(), caching the
Module instance in the ModuleDefinition would eliminate some complexity?

No. I actually think caching the Module instance in the ModuleDefinition
would add complexity to the design and the implementation. If the module
instances are cached in the ModuleSystem, the ModuleSystem could fully
control the access of these module instances and update/change them
internally. ModuleDefinition is supposed to be stateless, and I think it
should be kept this way.

Well, I agree in theory. But... I am struggling to understand how we
provide an isolation model. If:

- There is a 1:1 relation for ModuleDefinition<->Module instance, and
- Isolation requires separate Module instances, then
- Isolation requires separate ModuleDefinition instances

If this is our isolation model, then how does a ModuleSystem instance
support this? Clearly, it would need to keep a mapping from each
ModuleDefinition to its Module instance. How is this simpler, or better?

In your current model (just as in my detach() model), there is still a
1:1 from *at any given moment*, at least from the perspective of the
definition.

Are you thinking that the ModuleSystem would have to keep track of
released modules?


Isolation requires creating a separate repository instance that wraps
another, and hands out *copies* of definitions from the underlying
instance.

We simply need a standard way to make such a copy, one that does not
require knowing the actual subtype.

If I understand what you are trying to do, you want to construct a new
repository instance with module definitions that are based on some
module definitions in an existing repository instance. To do that, we
could either go with the approach of constructing new ModuleDefinition,
or as you suggested - cloning. However, I don't think cloning is the
right general solution here - there are many module definitions that are
unsuitable for cloning (e.g. platform module definitions). My assumption
is that the developer creating the separate repository instance is
possibly the one creating the original repository instance, so I don't
understand why he can't simply construct a new ModuleDefinition with an
existing ModuleDefinitionContent.

But this approach means that the wrapper must be tightly coupled to the
wrappee. While I can imagine this holding true in some cases, it
certainly doesn't seem like the common case.

Why should an applet container, for example, be required to know the
*type* of ModuleDefinition subclasses in the repository?

Providing some sort of copy() operation on the base class eliminates
this kind of coupling.


- Stanley

Reply via email to