JDK-8027351: (ref) Base's class finalize method not invoked if a private finalize method exists in its subclass
Peter Levart
peter.levart at gmail.com
Mon Nov 4 07:10:58 UTC 2013
On 11/04/2013 07:52 AM, Peter Levart wrote:
>>> Also VM.awaitBooted seems inherently risky as a general method as
>>> you would have to make sure that it is never called by the main VM
>>> initialization thread. Perhaps handle this in
>>> sun.misc.SharedSecrets.getJavaLangAccess so it is less 'general'?
>>
>> That sounds a good idea. Let me think about it and get back to this.
>>
>>> That said I think Peter may be right that there could be races with
>>> agents triggerring explicit finalization requests early in the VM
>>> initialization process - which means any blocking operation
>>> dependent on other parts of the initialization sequence could be
>>> problematic.
>>
>> Hmm... agents calling System.runFinalization during startup - like
>> Alan described, the agent is playing fire.
>
> Hi Mandy,
>
> Isn't System.runFinalization() just a "hint"? Like System.gc() for
> example...
>
> * <p>
> * Calling this method suggests that the Java Virtual Machine expend
> * effort toward running the <code>finalize</code> methods of objects
> * that have been found to be discarded but whose
> <code>finalize</code>
> * methods have not yet been run. When control returns from the
> * method call, the Java Virtual Machine has made a *best effort* to
> * complete all outstanding finalizations.
> * <p>
>
> Couldn't the request just be ignored when called before VM.isBooted()
> ? The finalizers will be executed nevertheless asynchronously later by
> the finalizer thread...
...if you do it like the following:
/* Called by Runtime.runFinalization() */
static void runFinalization() {
if (VM.isBooted()) { // ignore requests early in the VM boot-up sequence
forkSecondaryFinalizer(new Runnable() {
private volatile boolean running;
public void run() {
if (running)
return;
running = true;
for (;;) {
Finalizer f = (Finalizer)queue.poll();
if (f == null) break;
f.runFinalizer();
}
}
});
}
}
*and* use the SharedSecrets.getJavaLangAccess() directly, the code also
passes the formal proof of having no data races, since you have the
following sequence:
boot-up thread:
write to SharedSecrets.javaLangAccess
volatile write to VM.booted
thread calling getJavaLangAccess():
volatile read from VM.booted
read from SharedSecrets.javaLangAccess
I still don't see any advantage of caching JavaLangAccess instance in a
private static Finalizer.jla field other than to complicate synchronization.
Regards, Peter
More information about the core-libs-dev
mailing list