Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8287133

Retire Runtime.runFinalizersOnExit so that it always throws UOE

XMLWordPrintable

    • behavioral
    • low
    • Hide
      `Runtime.runFinalizersOnExit` was removed from Java 11 in 2018. A corpus analysis done at that time showed very few uses, and most of those were gone in later versions of the same software. A rerun of the corpus analysis done in 2022 found only a single direct use of `runFinalizersOnExit` and that was only in non-product builds. In light of that, it seems probable that retiring `runFinalizersOnExit` will have extremely minimal, perhaps even zero, real world impact.
      Show
      `Runtime.runFinalizersOnExit` was removed from Java 11 in 2018. A corpus analysis done at that time showed very few uses, and most of those were gone in later versions of the same software. A rerun of the corpus analysis done in 2022 found only a single direct use of `runFinalizersOnExit` and that was only in non-product builds. In light of that, it seems probable that retiring `runFinalizersOnExit` will have extremely minimal, perhaps even zero, real world impact.
    • Java API
    • SE

      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

            dholmes David Holmes
            dholmes David Holmes
            Alex Buckley, Andrew Haley, Iris Clark, Mandy Chung
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated:
              Resolved: