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