Module system notification mechanism
Gordon Hirsch
gordon.hirsch at SAS.COM
Fri Jul 20 12:35:59 PDT 2007
I've been meaning to chime in to agree with Bryan. I think the analogy
to <clinit> is apt.
It's clear to me that init()/release() are fundamentally useful. OSGi
provides a useful precedent here. As an OSGi user I often implement the
BundleActivator start() and/or stop() methods to manage resources that
are needed module-wide, or to install/uninstall various listeners, etc.
These facilities can be abused, but without them, module implementors
are forced to do all initialization lazily which is usually more complex
(especially to make it thread-safe).
So I'm strongly in favor of the suggested lifecycle hooks.
Bryan Atsatt wrote:
> Stanley M. Ho wrote:
>> Hi Bryan,
>>
>> Bryan Atsatt wrote:
>>> Um, I'm not arguing about the restriction in custom import policies, I
>>> certainly understand why that is present.
>>>
>>> I'm saying that an initializer *should* be able to rely on imported
>>> modules, so we need a separate mechanism. And that separate mechanism
>>> would kick in *after* resolution/validation had completed.
>>>
>>> And yes, there is potentially a pathological case even here, if two
>>> initializers have cyclic dependencies (not the Class kind ;^), but...
>>> Seems to me that this has to be discovered and eliminated in
>>> development; this is a variation on the "order of static initialization"
>>> problem, and one that we can't solve here.
>>
>> I think we agreed that in the presence of circular dependencies a module
>> cannot rely on its initializer being called before other code in the
>> module is called. The problem is that a module may not know if it is
>> part of a cyclic dependency chain because that depends on its imports,
>> their imports, etc. I don't think we can assume that this is a
>> pathological case that never occurs in the real world.
>
> Sure, it *can* happen, just like <clinit> execution order between
> classes can cause problems.
>
> But we still have class initializers in the language; I don't see this
> any differently. In the unusual case where a problem does occur, it must
> be fixed by refactoring the code in some fashion. So what? How can this
> be an argument that class initializers shouldn't exist?
>
> Sorry, Stanley, but I just don't buy this argument.
>
>> It is also unclear to me if providing the release() method would be
>> useful outside a container environment as well. As I hinted before, you
>> probably want to do the clean up in the finalizer or something similar
>> when nobody uses the module instance anymore, rather than when the
>> module instance is released from the module system while other existing
>> users could still access it.
>
> ARGH! Stanley, we've been going around in circles on this for years now
> :^). Yes, the lifecycle problem is made visible more often in container
> environments, but it is not limited to them: if this spec is going to
> enable a module to be released during the life of a process, then we've
> just pulled the problem directly into SE, container or no container.
>
> Your argument here is that since we cannot know whether a module's
> classes are in use *after* it has been released/uninstalled, informing
> the module that it has been released is pointless, since it cannot do
> anything meaningful.
>
> This is utter nonsense (sorry)! If a module requires some kind of
> initialization (whether we make it easy or not), it almost certainly
> needs to cleanup at some point. In your view, the way to accomplish such
> cleanup is during GC. In the real world, this is rarely sufficient: a
> single class leak (often caused by JRE classes!) will cause it to fail.
> And, often worse, the timing issue rears its ugly head: another
> module/class comes up that needs to acquire the same resources. This is
> then a race condition over which you have little control. GC is not the
> answer to all resource management.
>
> Proper resource management requires a well-defined lifecycle: threads,
> server sockets, client sockets, files, file locks, native library
> resources, external (server) resources, etc. all need to be explicitly
> managed.
>
> We need to at least give modules a well-defined time to release
> resources (and a module should be free to reject calls into it after
> those resources have been released).
>
> Either we should avoid this problem entirely by eliminating the ability
> to release modules, OR we should provide a means to solve the problem.
> Clearly, I am strongly in favor of the latter. And the solution should
> be symmetrical...
>
> It seems irresponsible in the extreme for this EG to waste the
> opportunity to introduce a standardized lifecycle, with both init and
> release calls to the module itself.
>
> // Bryan
>
> BTW: In the ModuleInitializer I suggested, I would provide no-op
> implementations for all the methods. If you don't care about
> getImports(), for example, you shouldn't have to do anything in your
> subclass.
More information about the jsr277-eg-observer
mailing list