JDK-8287133 : Retire Runtime.runFinalizersOnExit so that it always throws UOE
  • Type: CSR
  • Component: core-libs
  • Sub-Component: java.lang
  • Priority: P3
  • Status: Closed
  • Resolution: Approved
  • Fix Versions: 8u42
  • Submitted: 2022-05-23
  • Updated: 2022-07-29
  • Resolved: 2022-05-28
Related Reports
CSR :  
Relates :  
Description
Summary
-------

Retire `Runtime.runFinalizersOnExit` (and the associated `System.runFinalizersOnExit`) so that it always throws `UnsupportedOperationException`.

Problem
-------

The `Runtime.runFinalizersOnExit` method was deprecated in Java 1.2 and was removed in Java 11, under JDK-8198249. It is an inherently unsafe API for a number of reasons, as outlined in JDK-8198249.

Since removal of `Runtime.runFinalizersOnExit` in Java 11, the JDK's implementation of reference processing has established the invariant that processing of a `FinalReference` can only happen when the reference is inactive, that is, it is enqueued (or was enqueued) on its associated `ReferenceQueue`. This implementation has now been backported to JDK 8u42 as part of JSR 337 Maintenance Release 4. (8u42 is the RI of MR4.) The new invariant is incompatible with the operation of the `runFinalizersOnExit` logic.

Solution
--------

Retire `Runtime.runFinalizersOnExit` (and the associated `System.runFinalizersOnExit`) so that it always throws `UnsupportedOperationException`. 

Neither `Runtime.runFinalizersOnExit` nor `System.runFinalizersOnExit` will be removed, so they remain deprecated, not deprecated-for-removal.

Note that `Runtime.runFinalizersOnExit` is distinct from `Runtime.runFinalization`, which is unchanged.

Specification
-------------

The specification of `Runtime.runFinalizersOnExit` is updated to read:

    /**
     * Throws {@code UnsupportedOperationException}.
     *
     * @param value ignored
     *
     * @deprecated This method was originally designed to enable or disable
     * running finalizers on exit. Running finalizers on exit was disabled by default.
     * If enabled, then the finalizers of all objects whose finalizers had not
     * yet been automatically invoked were to be run before the Java runtime exits.
     * That behavior is inherently unsafe. It may result in finalizers being called
     * on live objects while other threads are concurrently manipulating those objects,
     * resulting in erratic behavior or deadlock.

The specification of `System.runFinalizersOnExit` is updated to read:

    /**
     * Throws {@code UnsupportedOperationException}.
     *
     * <p>The call {@code System.runFinalizersOnExit()} is effectively
     * equivalent to the call:
     * <blockquote><pre>
     * Runtime.runFinalizersOnExit()
     * </pre></blockquote>
     *
     * @param value ignored
     *
     * @deprecated This method was originally designed to enable or disable
     * running finalizers on exit. Running finalizers on exit was disabled
     * by default. If enabled, then the finalizers of all objects whose
     * finalizers had not yet been automatically invoked were to be run before
     * the Java runtime exits. That behavior is inherently unsafe. It may
     * result in finalizers being called on live objects while other threads
     * are concurrently manipulating those objects, resulting in erratic
     * behavior or deadlock.
     *
     * @see java.lang.Runtime#runFinalizersOnExit(boolean)
     * @since JDK1.1
     */

The references to "running finalizers on exit" in `Runtime.exit`, `Runtime.addShutdownHook`, , and `Runtime.halt` are all removed. Their specifications read the same as they did for Java 11.

First `Runtime.exit`:

    -     * <p> The virtual machine's shutdown sequence consists of two phases.  In
    -     * the first phase all registered {@link #addShutdownHook shutdown hooks},
    -     * if any, are started in some unspecified order and allowed to run
    -     * concurrently until they finish.  In the second phase all uninvoked
    -     * finalizers are run if {@link #runFinalizersOnExit finalization-on-exit}
    -     * has been enabled.  Once this is done the virtual machine {@link #halt
    -     * halts}.
    -     *
    -     * <p> If this method is invoked after the virtual machine has begun its
    -     * shutdown sequence then if shutdown hooks are being run this method will
    -     * block indefinitely.  If shutdown hooks have already been run and on-exit
    -     * finalization has been enabled then this method halts the virtual machine
    -     * with the given status code if the status is nonzero; otherwise, it
    +     * <p> All registered {@linkplain #addShutdownHook shutdown hooks}, if any,
    +     * are started in some unspecified order and allowed to run concurrently
    +     * until they finish.  Once this is done the virtual machine
    +     * {@linkplain #halt halts}.
    +     *
    +     * <p> If this method is invoked after all shutdown hooks have already
    +     * been run and the status is nonzero then this method halts the
    +     * virtual machine with the given status code. Otherwise, this method
          * blocks indefinitely.
          *
Next `Runtime.addShutdownHook`:

          * them run concurrently.  When all the hooks have finished it will then
    -     * run all uninvoked finalizers if finalization-on-exit has been enabled.
    -     * Finally, the virtual machine will halt.  Note that daemon threads will
    -     * continue to run during the shutdown sequence, as will non-daemon threads
    -     * if shutdown was initiated by invoking the <tt>{@link #exit exit}</tt>
    -     * method.
    +     * halt. Note that daemon threads will continue to run during the shutdown
    +     * sequence, as will non-daemon threads if shutdown was initiated by
    +     * invoking the {@link #exit exit} method.
          *

Then `Runtime.halt`:

         * <p> This method should be used with extreme caution.  Unlike the
    -     * <tt>{@link #exit exit}</tt> method, this method does not cause shutdown
    -     * hooks to be started and does not run uninvoked finalizers if
    -     * finalization-on-exit has been enabled.  If the shutdown sequence has
    -     * already been initiated then this method does not wait for any running
    -     * shutdown hooks or finalizers to finish their work. <p>
    +     * {@link #exit exit} method, this method does not cause shutdown
    +     * hooks to be started.  If the shutdown sequence has already been
    +     * initiated then this method does not wait for any running
    +     * shutdown hooks to finish their work.

Full specdiff: http://cr.openjdk.java.net/~dholmes/8287132-specdiff/overview-summary.html


Comments
Moving to Approved.
28-05-2022

Moving to Provisional, not Approved. [~mchung] or [~kbarrett], please also review this CSR.
24-05-2022