Consider the following Java class:
class X {
public void foo() {
bar = 1;
}
protected void finalize() {
if (bar == 1)
baz();
}
private int bar = 0;
}
Under the assumption that X.foo()
is never called from any finalize()
method (directly or indirectly), can I be sure that the code above is free of data-races, that is, can I be sure that X.finalize()
sees the value written by X.foo()
in every case where X.foo()
is actually called?
The naive analysis would say that X.finalize()
cannot run concurrently with X.foo()
(due to the mentioned assumption), so no extra synchronization is necessary.
I would guess that the code above is free of data races, but it troubles me that the language specification contains the following explicit statement in §17.4.5, but says nothing about a happens-before relationship between finalize() and methods in general:
There is a happens-before edge from the end of a constructor of an object to the start of a finalizer (§12.6) for that object.
EDIT: I see the need to make my question more precise, so here is an attempt at a precise reformulation of the question:
Does Java guarantee a happens-before relation between a specific method X.foo()
and X.finalize()
if I guarantee that X.foo()
is never called (directly or indirectly) from any finalize()
method? Here, happens-before is to be interpreted exactly as defined in §17.4.5.
Setting/Getting an int value in Java is atomic anyway AFAIK.
So I don't think you should worry.
"but says nothing about a happens-before relationship
between finalize() and methods in general"
That's because those methods (in general) are not managed/called
by the JVM but by you. So it cannot say anything.
By the way if app code can still call foo(), it means this app
code has reference to your object so your object is not eligible
for garbage collection (i.e. for finalize() to be called).
So, you know, I doubt your concern has grounds at all.
UPDATE:
"Does Java guarantee a happens-before relation between a specific method X.foo() and
X.finalize() if I guarantee that X.foo() is never called (directly or indirectly) from
any finalize() method"
Assume the opposite -> Imagine the situation you get.
The finalize() method was called on object x; then somebody calls foo() on this object x (note: x is already dead i.e. garbage collected) object. Does that sound possible? Not to me.