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

Reply via email to