finalize() allowed to be called before constructor finishes?

Discussion in 'Java' started by Boris, Apr 20, 2007.

  1. Boris

    Boris Guest

    Is there any guarantee that finalize() is called only after a constructor
    finishes? I wonder as the documentation at
    http://java.sun.com/javase/6/docs/api/java/lang/Object.html#finalize()
    says that the "Java programming language does not guarantee which thread
    will invoke the finalize method".

    I ask as I have a Java class which makes two JNI calls in the constructor.
    In finalize() another JNI call is made to release resources. If the class
    is instantiated thousands of times in a loop without storing references I
    get an exception or crash at some point as the second call in the
    constructor tries to use a resource which strangely has been released
    already. If I change the program and store references to make sure that
    the garbage collector releases all objects only after the loop everything
    works fine. I'm now trying to understand if there is a race condition as
    the second JNI call in the constructor doesn't see the resource sometimes.
    Any ideas?

    Thanks in advance,
    Boris
     
    Boris, Apr 20, 2007
    #1
    1. Advertising

  2. Boris

    Stefan Ram Guest

    Boris <> writes:
    >Is there any guarantee that finalize() is called only after a
    >constructor finishes?


    »A finalizer may be invoked explicitly,
    just like any other method.«

    JLS3, 12.6

    http://java.sun.com/docs/books/jls/third_edition/html/execution.html#12.6

    Thus, a constructor might call »finalize()« itself before it
    (i.e., the constructor) is finished (unless this is forbidden
    somewhere else).

    This would mean that there is no such guarantee.
     
    Stefan Ram, Apr 21, 2007
    #2
    1. Advertising

  3. Boris wrote:
    > Is there any guarantee that finalize() is called only after a
    > constructor finishes? I wonder as the documentation at
    > http://java.sun.com/javase/6/docs/api/java/lang/Object.html#finalize()
    > says that the "Java programming language does not guarantee which thread
    > will invoke the finalize method".
    >
    > I ask as I have a Java class which makes two JNI calls in the
    > constructor. In finalize() another JNI call is made to release
    > resources. If the class is instantiated thousands of times in a loop
    > without storing references I get an exception or crash at some point as
    > the second call in the constructor tries to use a resource which
    > strangely has been released already. If I change the program and store
    > references to make sure that the garbage collector releases all objects
    > only after the loop everything works fine. I'm now trying to understand
    > if there is a race condition as the second JNI call in the constructor
    > doesn't see the resource sometimes. Any ideas?


    I'm assuming you do not have any explicit finalize() calls in the
    constructor.

    According to the JLS "The completion of an object's constructor
    happens-before (§17.4.5) the execution of its finalize method (in the
    formal sense of happens-before)."

    [12.6 Finalization of Class Instances,
    http://java.sun.com/docs/books/jls/third_edition/html/execution.html#12.6]

    I would start looking for exactly what resource is involved, and how
    actions involved in it are synchronized.

    Patricia
     
    Patricia Shanahan, Apr 21, 2007
    #3
  4. Boris

    Boris Guest

    On Sat, 21 Apr 2007 02:22:06 +0300, Patricia Shanahan <> wrote:

    > [...]I'm assuming you do not have any explicit finalize() calls in the
    > constructor.


    Yes, no explicit finalize() call.

    > According to the JLS "The completion of an object's constructor
    > happens-before (§17.4.5) the execution of its finalize method (in the
    > formal sense of happens-before)."
    >
    > [12.6 Finalization of Class Instances,
    > http://java.sun.com/docs/books/jls/third_edition/html/execution.html#12.6]
    >
    > I would start looking for exactly what resource is involved, and how
    > actions involved in it are synchronized.


    Hm, is it possible that because JNI is involved things might be more
    complicated? I'm rather guessing here but the code is pretty simple. I'll
    check everything again but to give you an idea - this code fails:

    for (int i = 0; i < 100000; ++i)
    {
    createAndReturnObject();
    }

    And this code works:

    Vector v = new Vector(100000);
    for (int i = 0; i < 100000; ++i)
    {
    v.add(createAndReturnObject());
    }

    That's why I assume that the garbage collector causes some problems here.
    I don't know if JNI functions are or can be invoked on another thread? Or
    the garbage collector's thread is not properly synchronized with JNI
    calls? If there are any other ideas I'd like to hear them.

    Boris
     
    Boris, Apr 21, 2007
    #4
  5. Boris wrote:
    > On Sat, 21 Apr 2007 02:22:06 +0300, Patricia Shanahan <> wrote:
    >
    >> [...]I'm assuming you do not have any explicit finalize() calls in the
    >> constructor.

    >
    > Yes, no explicit finalize() call.
    >
    >> According to the JLS "The completion of an object's constructor
    >> happens-before (§17.4.5) the execution of its finalize method (in the
    >> formal sense of happens-before)."
    >>
    >> [12.6 Finalization of Class Instances,
    >> http://java.sun.com/docs/books/jls/third_edition/html/execution.html#12.6]
    >>
    >>
    >> I would start looking for exactly what resource is involved, and how
    >> actions involved in it are synchronized.

    >
    > Hm, is it possible that because JNI is involved things might be more
    > complicated? I'm rather guessing here but the code is pretty simple.
    > I'll check everything again but to give you an idea - this code fails:
    >
    > for (int i = 0; i < 100000; ++i)
    > {
    > createAndReturnObject();
    > }
    >
    > And this code works:
    >
    > Vector v = new Vector(100000);
    > for (int i = 0; i < 100000; ++i)
    > {
    > v.add(createAndReturnObject());
    > }
    >
    > That's why I assume that the garbage collector causes some problems
    > here. I don't know if JNI functions are or can be invoked on another
    > thread? Or the garbage collector's thread is not properly synchronized
    > with JNI calls? If there are any other ideas I'd like to hear them.
    >
    > Boris


    I'm sure there is something involved in the JNI work that causes your
    problem. In particular, do you ensure that the JNI work is completely
    finished before the constructor continues executing? Is there anything
    in the JNI code that is shared between objects?

    Patricia
     
    Patricia Shanahan, Apr 21, 2007
    #5
  6. Boris

    Boris Guest

    On Sat, 21 Apr 2007 03:31:51 +0300, Patricia Shanahan <> wrote:

    > [...]I'm sure there is something involved in the JNI work that causes
    > your
    > problem. In particular, do you ensure that the JNI work is completely
    > finished before the constructor continues executing? Is there anything


    Is there anything I need to do to ensure it? Doesn't Java have to wait
    until JNI calls return (my DLL is singe-threaded, and the JNI functions
    return results which are used in the constructor)?

    > in the JNI code that is shared between objects?


    That's a good point. If I think about it the problem might arise from the
    fact that finalize() can be invoked at any time on any thread. I think I
    can rely on constructors being called one after another in a loop. And as
    I learnt I can also rely on finalize() being called after the constructor
    of the same object. However I can't rely on finalize() being called while
    no constructor for another object is running. And as my DLL uses a
    C++ container to track all resources this container might be used from two
    threads at the very same time - one adding a resource, another one
    removing another resource.

    Thanks for your comments, Patricia! They were very helpful! I'll look go
    back to code and check the details.

    Boris
     
    Boris, Apr 21, 2007
    #6
  7. Boris wrote:
    > On Sat, 21 Apr 2007 03:31:51 +0300, Patricia Shanahan <> wrote:
    >
    >> [...]I'm sure there is something involved in the JNI work that causes
    >> your
    >> problem. In particular, do you ensure that the JNI work is completely
    >> finished before the constructor continues executing? Is there anything

    >
    > Is there anything I need to do to ensure it? Doesn't Java have to wait
    > until JNI calls return (my DLL is singe-threaded, and the JNI functions
    > return results which are used in the constructor)?


    I was thinking about the possibility of multi-threading in the DLL.

    >
    >> in the JNI code that is shared between objects?

    >
    > That's a good point. If I think about it the problem might arise from
    > the fact that finalize() can be invoked at any time on any thread. I
    > think I can rely on constructors being called one after another in a
    > loop. And as I learnt I can also rely on finalize() being called after
    > the constructor of the same object. However I can't rely on finalize()
    > being called while no constructor for another object is running. And as
    > my DLL uses a C++ container to track all resources this container might
    > be used from two threads at the very same time - one adding a resource,
    > another one removing another resource.


    That container seems like a good candidate.

    Assuming a single garbage collection thread, delaying unreachability of
    any of the objects until after the last construction would limit the
    container to being accessed from one thread at a time, preventing the
    problem.

    Patricia
     
    Patricia Shanahan, Apr 21, 2007
    #7
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Paul J. Lucas
    Replies:
    117
    Views:
    12,750
    Tim Tyler
    Sep 27, 2005
  2. Paul Tomblin
    Replies:
    18
    Views:
    522
    Piotr Kobzda
    Apr 26, 2007
  3. andrey
    Replies:
    0
    Views:
    173
    andrey
    Dec 15, 2007
  4. Andrey Nikitin
    Replies:
    1
    Views:
    179
    Nobuyoshi Nakada
    Dec 16, 2007
  5. Graham J
    Replies:
    2
    Views:
    118
    Graham J
    Sep 20, 2003
Loading...

Share This Page