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

Remove the terminally deprecated finalize() method from javax.imageio.stream APIs

XMLWordPrintable

    • behavioral
    • medium
    • Hide
      Since disposer/cleaner is used to free resources used by all JDK-provided classes, the only risk to applications using only these is limited to clients which choose to use FileCacheImageOutputStream.java or MemoryFileCacheImageOutputStream.java and do not 'flush' these streams to the java.io.OutputStream destination (note that the ImageIO streams never close the destination stream).
      The close() methods for these ImageIO (not java.io) streams do flush, and finalize() calls close() so these are currently guaranteed to be flushed before being finalized. This will no longer be possible.
      However, all the JDK-provided ImageWriters will flush at the end of writing an image so that should not be a problem. It is a potential concern for using a 3rd party ImageWriter which does not flush, but in reality if finalization() is how the data gets flushed, the destination java.io.OutputStream is unlikely to be still available or in a state to receive that flushed data.
      So the most likely compatibility issue is for a 3rd party javax.imageio.OutputStream which has only finalize() to 'backstop' the failure of a client to call close(), and that 3rd party plugin stream allocates resources which need to be released. The principal example of that is the JAI Image I/O tools, which have streams use a java.nio FileChannel. However that package has been unsupported for a long time. Applications which use it would need to ensure they call close() directly.
      Show
      Since disposer/cleaner is used to free resources used by all JDK-provided classes, the only risk to applications using only these is limited to clients which choose to use FileCacheImageOutputStream.java or MemoryFileCacheImageOutputStream.java and do not 'flush' these streams to the java.io.OutputStream destination (note that the ImageIO streams never close the destination stream). The close() methods for these ImageIO (not java.io) streams do flush, and finalize() calls close() so these are currently guaranteed to be flushed before being finalized. This will no longer be possible. However, all the JDK-provided ImageWriters will flush at the end of writing an image so that should not be a problem. It is a potential concern for using a 3rd party ImageWriter which does not flush, but in reality if finalization() is how the data gets flushed, the destination java.io.OutputStream is unlikely to be still available or in a state to receive that flushed data. So the most likely compatibility issue is for a 3rd party javax.imageio.OutputStream which has only finalize() to 'backstop' the failure of a client to call close(), and that 3rd party plugin stream allocates resources which need to be released. The principal example of that is the JAI Image I/O tools, which have streams use a java.nio FileChannel. However that package has been unsupported for a long time. Applications which use it would need to ensure they call close() directly.
    • Java API
    • SE

      Summary

      finalize() is removed from javax.imageio.ImageInputStreamImpl and its subclasses.

      Problem

      javax.imageio.stream.ImageInputStreamImpl is the parent class of all the implementations of ImageInputStream and ImageOutputStream in the javax.imageio API and it defines finalize() as a last resort backstop to properly call close() and free internal resources. 3rd party sub-classes which derive from ImageInputStreamImpl may also rely on finalization. However finalization is deprecated for removal by JEP 421 https://openjdk.org/jeps/421.

      Solution

      To the extent possible, replace finalization with other mechanisms to free resources. Document the requirements on applications to ensure resources are freed.

      The principal alternate mechanism is a "cleaner". Not java.lang.ref.Cleaner, but a very similar internal class used in the java.desktop module. And this is in fact already used by most of the concrete javax.imageio.stream classes, and these over-ride finalize() to be empty, thus avoiding finalization. These empty over-rides are now removed (see Specification).

      The two classes that still used finalization : javax/imageio/stream/FileCacheImageOutputStream.java and javax/imageio/stream/MemoryCacheImageOutputStream.java

      are un-changed in javadoc, because they inherited the ImageInputStreamImpl.java default finalize() method. However the package documentation is now updated to inform applications of the need to call close() and internally a disposer/cleaner will ensure native resources are freed for these JDK classes. See the compatibility risk section for more details.

      Specification

      javax/imageio/stream/package-info.java

      + * An {@code ImageInputStream} or {@code ImageOutputStream} may internally allocate
      + * system resources, such as a temporary cache file.
      + * Clients are encouraged to use a try-with-resources statement to ensure the
      + * {@link ImageInputStream#close()} or {@link ImageOutputStream#close()}
      + * method is called which can promptly free those native resources.
      + * Otherwise there is the possibility they will leak and eventually cause the
      + * application to fail as well the possibility that not all data is flushed
      + * to the underlying output stream. A logical consequence of that is that
      + * this should be done before closing the destination {@link java.io.OutputStream}.
      + * A simple pattern would be
      + * {@snippet lang='java':
      + * try (FileOutputStream fos = new FileOutputStream("out.jpg");
      + *      ImageOutputStream ios = new FileCacheImageOutputStream(fos, null)) {
      + *     ImageIO.write(img, "jpg", ios);
      + * } catch (IOException e) {
      + * } // implicit finally block closes the streams in the reverse order to opening
      + * }
      + * <p>
      + * Sub-classers of these Image I/O API stream types can, to a limited extent, protect
      + * the application from the consequences of failures to close by adopting mechanisms
      + * such as {@link java.lang.ref.Cleaner} to free internal resources when it
      + * is no longer reachable. This is only necessary if there are any resources to release.
      + * However applications cannot rely on this, either for resource management, or
      + * for program correctness.
      
      

      javax/imageio/stream/ImageInputStreamImpl.java - remove finalize from abstract base class.

      -    /** 
      -     * Finalizes this object prior to garbage collection.  The
      -     * {@code close} method is called to close any open input
      -     * source.  This method should not be called from application
      -     * code.
      -     *      
      -     * @throws Throwable if an error occurs during superclass
      -     * finalization.
      -     *  
      -     * @deprecated Finalization has been deprecated for removal.  See
      -     * {@link java.lang.Object#finalize} for background information and details
      -     * about migration options.
      -     */
      -    @Deprecated(since="9", forRemoval=true)
      -    @SuppressWarnings("removal")
      -    protected void finalize() throws Throwable
      

      javax/imageio/stream/FileCacheImageInputStream.java - remove empty finalize override

      -    /**
      -     * {@inheritDoc}
      -     *
      -     * @deprecated Finalization has been deprecated for removal.  See
      -     * {@link java.lang.Object#finalize} for background information and details
      -     * about migration options.
      -     */
      -    @Deprecated(since="9", forRemoval=true)
      -    @SuppressWarnings("removal")
      -    protected void finalize() throws Throwable 
      

      javax/imageio/stream/FileImageInputStream.java - remove empty finalize override

      -    /**
      -     * {@inheritDoc}
      -     *
      -     * @deprecated Finalization has been deprecated for removal.  See
      -     * {@link java.lang.Object#finalize} for background information and details
      -     * about migration options.
      -     */
      -    @Deprecated(since="9", forRemoval=true)
      -    @SuppressWarnings("removal")
      -    protected void finalize() throws Throwable
      

      javax/imageio/stream/FileImageOutputStream.java - remove empty finalize override

      -    /**
      -     * {@inheritDoc}
      -     *
      -     * @deprecated Finalization has been deprecated for removal.  See
      -     * {@link java.lang.Object#finalize} for background information and details
      -     * about migration options.
      -     */
      -    @Deprecated(since="9", forRemoval=true)
      -    @SuppressWarnings("removal")
      -    protected void finalize() throws Throwable
      

      javax/imageio/stream/MemoryCacheImageInputStream.java - remove empty finalize override

      -    /**
      -     * {@inheritDoc}
      -     *
      -     * @deprecated Finalization has been deprecated for removal.  See
      -     * {@link java.lang.Object#finalize} for background information and details
      -     * about migration options.
      -     */
      -    @Deprecated(since="9", forRemoval=true)
      -    @SuppressWarnings("removal")
      -    protected void finalize() throws Throwable
      

            prr Philip Race
            prr Philip Race
            Alexander Zvegintsev
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved: