On Sat, Dec 13, 2003 at 07:29:10AM +0100, Stephen McConnell wrote: > > Niclas Hedhman wrote: > > >On Saturday 13 December 2003 03:29, Stephen McConnell wrote: > > > >>>a) It is possible that the finalize() of the component, or the > >>>finalize() of any other object referred by the component is already > >>>invoked before the finalize() of the proxy is invoked. So dispose() will > >>>find itself in an abnormal situation, where some of the object are > >>>already finalized, or even worst, just being concurrently finalized in > >>>another thread.
Correct. > >>No - its not possible. The proxy holds a hard reference to the > >>component so the component cannot be finalized before the proxy. Incorrect - finalizer-reachable objects may still be finalized. > >If you haven't gotten the point from Daniel and Timothy, you are wrong; > > > >Holding a strong reference guarantee nothing, only if you can guarantee > >something else is holding a strong reference to the Proxy, in which case > >the finalize() on the proxy won't be called either.... Right'ish. Whether another object holds a reference to a given object is, by itself, irrelevant to the garbage collector. What _is_ relevant is whether the object is A) reachable from the _root set_ (typically just referred to as "reachable"), or B) whether it's reachable from a not reachable and not finalized object that has a finalizer (termed "finalizer-reachable"). [snip] > In the first case - the managing appliance holds a reference to the > proxy for the life of the appliance. In the second case the consumer > holds a reference for as long as it needs to. Once the proxy reference > is released - we then have the potential for the collection of the proxy > by the garbage collector. The issue raised by Daniel is that the > component may potentially be garbage collected before the proxy is > garbage collected. My assertion is that this is not the case - on the > grounds that the proxy holds the reference to the component - therefore > the component will not be included in a GC pass until the proxy has be > GC'ed. If the component held a reference to its proxy - then - and only > then - would the proxy and component instance potentially be subject to > GC'ing in the same pass. Timothy's email confirms the assumptions I'm > making - in particular the fact that the reference by the proxy to the > component instance cannot be ignored by a GC system - because finalize > is a method acting of valid variables within the scope of the proxy class. > > The point of contention is the subject of the unreachable status of the > component instance. I agree that the specs on what is and what isn't > unreachable are vauge - and I also would agree that the strategy in > Merlin is leveraging demonstrated behaviour (in partiular - the proxy > and component do *not* get gc'ed in the same pass). So on one hand we > have a default behaviour which equates to hard references that depend on > release by the client, while enabling more liberal policies that simply > make a lot of sense with transient component handling. But I would also > assert that you cannot (at the system level) do it differently - a > variable assigned in a non-finalized instance cannot magically dissapear > (and if it could the finalize method would make absolutely no sense). > In particular - the implementation of finalize makes the proxy reachable > by a thread and therfore all variables held by the proxy are reachable > therefore all referenced instances cannot be colected before the proxy > is itself collected (i.e. post execution of finalize). I think two issues are being confused here: reachability and finalization. Yes, the two are somewhat related, but because a finalizer can resurect objects an object can be both fully reachable and finalized. And an object may have its finalizer invoked even when it's finalizer-reachable (which is what the component is when the proxy becomes unreachable and hasn't been finalized). Section 12.6.1 of the JLS 2.0 is a good read for this. The upshot is this: Yes, it's safe(*) to invoke the component's dispose() from the proxy's finalize(), as you're guaranteed that the component is still accessible. However, the component may have already had its finalizer invoked, or may even have its finalizer being invoked concurrently. So Daniel's point a) above is correct (see also section 12.6.2 of JLS 2.0). All this really means, btw., is that components should not have a finalize() method, but should instead treat dispose() as their finalizer. (*) for some values of safe > Wow - this is getting deep! Yup. Cheers, Ronald --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
