If I am not mistaken, finalization order is not guaranteed by the VM.
Therefore, in the case of a circular reference, you really can't know
whether the finalize method will be called on "a" or "b" first. But then,
who really cares?
My point is this. All references that are reachable by a particular object
ARE STILL reachable to that object when its finalize() method is called.
How else would finalize be useful to perform cleanup operations? Objects
are discarded some time after finalize(). But there is a guarantee. Before
an object is discarded, any object that references that object will have its
finalize() method invoked. Just read the following snipet from the API docs
for Object.finalize().
Called by the garbage collector on an object when garbage collection
determines that there are no more references to the object. A subclass
overrides the finalize method to dispose of system resources or to perform
other cleanup.
The general contract of finalize is that it is invoked if and when the
JavaTM virtual machine has determined that there is no longer any means by
which this object can be accessed by any thread that has not yet died,
except as a result of an action taken by the finalization of some other
object or class which is ready to be finalized. The finalize method may take
any action, including making this object available again to other threads;
the usual purpose of finalize, however, is to perform cleanup actions before
the object is irrevocably discarded. For example, the finalize method for an
object that represents an input/output connection might perform explicit I/O
transactions to break the connection before the object is permanently
discarded.
The finalize method of class Object performs no special action; it simply
returns normally. Subclasses of Object may override this definition.
The Java programming language does not guarantee which thread will invoke
the finalize method for any given object. It is guaranteed, however, that
the thread that invokes finalize will not be holding any user-visible
synchronization locks when finalize is invoked. If an uncaught exception is
thrown by the finalize method, the exception is ignored and finalization of
that object terminates.
After the finalize method has been invoked for an object, no further action
is taken until the Java virtual machine has again determined that there is
no longer any means by which this object can be accessed by any thread that
has not yet died, including possible actions by other objects or classes
which are ready to be finalized, at which point the object may be discarded.
The finalize method is never invoked more than once by a Java virtual
machine for any given object.
Any exception thrown by the finalize method causes the finalization of this
object to be halted, but is otherwise ignored.
> Sorry, I don't get it... Does the -- obviously correct -- statement "the
> component will never become unreachable before the finalize() method in
> the Proxy" prove what? I belive it does *not* prove that:
>
> a)
>
> The soft ref. to the proxy can't be cleared earlier that its
> finalize() method is executed.
>
> The docs of lang.ref doesn't talk about
> reachable/f-reachable/unreachable: "An object is strongly reachable if
> it can be reached by some thread without traversing any reference
> objects. A newly-created object is strongly reachable by the thread that
> created it. An object is softly reachable if it is not *strongly
> reachable* but can be reached by traversing a soft reference." Again, if
> it is not "strongly reachable", and not if "not reachable". One may
> argue, that "can be reached by some thread without traversing any
> reference objects" stand only when the object is already entered of left
> the last stage (unerachable/finalized). But I'm pretty sure it's not the
> case, since I know from experiment that Sun JVM used to clear weak
> references approximately at the moment of finalize() invocation (it's
> not measurable if it is before that or just after that), and does not
> wait until finalize() returns, so it cleanly does not wait for state
> change "F". And, soft refs are cleared before weak refs.
>
> b) The component can't enter "finalized" state before the proxy enters
> "finalized". Anyway, it is just proved to be false empirically:
>
> I have made an experiment regarding b). It cleanly shows that the
> component is possibly finalized before the proxy, on the JVM comes with
> Sun's J2SE 1.4.2 for Windows.
>
> <code file="Test.java">
> import java.lang.ref.*;
>
> public class Test {
> public static void main(String[] args) throws Throwable {
> A c = new A("component", null);
> A p = new A("proxy", c);
> c = null;
> p = null;
>
> for (int i = 0; i < 10000; i++) {
> System.gc();
> Thread.sleep(100);
> }
> }
> }
>
> class A {
> private final String m_id;
> private final A m_refed;
>
> int[] m_eatMemory = new int[1024*256];
>
> public A(String id, A refed) {
> m_id = id;
> m_refed = refed;
> }
>
> public void finalize() throws Throwable {
> p("finalize() started for " + m_id
> + " (stores ref to: "
> + (m_refed != null ? m_refed.m_id : "null") + ")");
> Thread.sleep(1000);
> p("finalize() ended for " + m_id);
> }
>
> public static void p(Object o) {
> synchronized(System.out) {
> System.out.println(o.toString());
> System.out.flush(); // You never know... :)
> }
> }
> }
> </code>
>
> When I run this, I get:
>
> finalize() started for component (stores ref to: null)
> finalize() ended for component
> finalize() started for proxy (stores ref to: component)
> finalize() ended for proxy
>
> Ops! And, when I replace the first 4 line of main(...) with this:
>
> A p = new A("proxy", new A("component", null));
> p = null;
>
> then I get:
>
> finalize() started for proxy (stores ref to: component)
> finalize() ended for proxy
> finalize() started for component (stores ref to: null)
> finalize() ended for component
>
> So it seems the it is rather creation order that has influenced the
> order if finalize() calls, and not the structure of the reference graph.
>
> --
> Best regards,
> Daniel Dekany
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [EMAIL PROTECTED]
> For additional commands, e-mail: [EMAIL PROTECTED]
>
>
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]