finalize() allowed to be called before constructor finishes?

B

Boris

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
 
S

Stefan Ram

Boris said:
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.
 
P

Patricia Shanahan

Boris said:
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
 
B

Boris

[...]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
 
P

Patricia Shanahan

Boris said:
[...]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
 
B

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

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
 
P

Patricia Shanahan

Boris said:
[...]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.
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
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top