JDK-8353710 : DeflaterInput/OutputStream and InflaterInput/OutputStream should explain responsibility for freeing resources
  • Type: CSR
  • Component: core-libs
  • Sub-Component: java.util.jar
  • Priority: P5
  • Status: Closed
  • Resolution: Approved
  • Fix Versions: 25
  • Submitted: 2025-04-04
  • Updated: 2025-04-08
  • Resolved: 2025-04-08
Related Reports
CSR :  
Description
Summary
-------

The specification of `java.util.zip.DeflaterOutputStream`,
`java.util.zip.DeflaterInputStream`, `java.util.zip.InflaterInputStream`
and `java.util.zip.InflaterOutputStream` classes will be enhanced
to specify the usage and closure of `java.util.zip.Deflater` and
`java.util.zip.Inflater` instances by these classes.

Problem
-------

The implementation of `DeflaterOutputStream` and `DeflaterInputStream`
uses `Deflater` instance to compress the stream data. Each of these
classes have more than one constructor to construct the stream.
Some of these constructors allow application code to pass a `Deflater`
instance whereas some other constructors do not accept a `Deflater`
and instead create a `Deflater` instance of their own. When the
stream is closed, the current implementation of these classes close
the `Deflater` instance if the stream was constructed without being
passed a `Deflater`. On the other hand, if a `Deflater` was passed
during construction of the stream, the application code is expected
to close that `Deflater` instance after the stream has been closed.

Similar implementation resides in `InflaterOutputStream` and
`InflaterInputStream` classes which can be constructed either by
passing a `Inflater` or the `Inflater` being created by the stream
during construction.

Neither of these classes specify that the application code needs to
take responsibility of closing the `Deflater`/`Inflater` instance
if the stream was constructed by passing it the `Deflater`/`Inflater`.

Solution
--------

The specification of these 4 classes will be updated to match the
current implementation and clarify the responsibility of the application
code when dealing with the `Deflater`/`Inflater` instance.

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

    diff --git a/src/java.base/share/classes/java/util/zip/DeflaterInputStream.java b/src/java.base/share/classes/java/util/zip/DeflaterInputStream.java
    + * <h2 id="compressor-usage">Compressor Usage</h2>
    + * A {@code DeflaterInputStream} created without
    + * specifying a {@linkplain Deflater compressor} will create a compressor
    + * at construction time, and close the compressor when the input stream
    + * is {@linkplain #close closed}.
    + * <p>
    + * If a compressor is specified when creating a {@code DeflaterInputStream}, it is the
    + * responsibility of the caller to {@linkplain Deflater#close close} the
    + * compressor after closing the input stream.
    + *
    + * @apiNote
    + * The {@link #close} method should be called to release resources used by this
    + * stream, either directly, or with the {@code try}-with-resources statement.
    + *
    @@ -68,8 +82,11 @@ private void ensureOpen() throws IOException {
         }
     
         /**
    -     * Creates a new input stream with a default compressor and buffer
    -     * size.
    +     * Creates a new input stream and compressor with the
    +     * default compression level and a default buffer size.
    +     * <p>
    +     * The compressor will be closed when this input stream
    +     * is {@linkplain #close() closed}.
          *
          * @param in input stream to read the uncompressed data to
          * @throws NullPointerException if {@code in} is null
    @@ -82,6 +99,10 @@ public DeflaterInputStream(InputStream in) {
         /**
          * Creates a new input stream with the specified compressor and a
          * default buffer size.
    +     * <p>
    +     * {@linkplain #close() Closing} this input stream
    +     * {@linkplain ##compressor-usage will not close} the given
    +     * {@linkplain Deflater compressor}.
          *
          * @param in input stream to read the uncompressed data to
          * @param defl compressor ("deflater") for this stream
    @@ -94,6 +115,10 @@ public DeflaterInputStream(InputStream in, Deflater defl) {
         /**
          * Creates a new input stream with the specified compressor and buffer
          * size.
    +     * <p>
    +     * {@linkplain #close() Closing} this input stream
    +     * {@linkplain ##compressor-usage will not close} the given
    +     * {@linkplain Deflater compressor}.
          *
          * @param in input stream to read the uncompressed data to
          * @param defl compressor ("deflater") for this stream
    @@ -123,6 +148,7 @@ public DeflaterInputStream(InputStream in, Deflater defl, int bufLen) {

    diff --git a/src/java.base/share/classes/java/util/zip/DeflaterOutputStream.java b/src/java.base/share/classes/java/util/zip/DeflaterOutputStream.java
    + * <h2 id="compressor-usage">Compressor Usage</h2>
    + * A {@code DeflaterOutputStream} created without
    + * specifying a {@linkplain Deflater compressor} will create a compressor
    + * at construction time, and close the compressor when the output stream
    + * is {@linkplain #close closed}.
    + * <p>
    + * If a compressor is specified when creating a {@code DeflaterOutputStream}, it is the
    + * responsibility of the caller to {@linkplain Deflater#close close} the
    + * compressor after closing the output stream.
    + *
    + * @apiNote
    + * The {@link #close} method should be called to release resources used by this
    + * stream, either directly, or with the {@code try}-with-resources statement.
    + *
    @@ -63,6 +77,10 @@ public class DeflaterOutputStream extends FilterOutputStream {
         /**
          * Creates a new output stream with the specified compressor,
          * buffer size and flush mode.
    +     * <p>
    +     * {@linkplain #close() Closing} this output stream
    +     * {@linkplain ##compressor-usage will not close} the given
    +     * {@linkplain Deflater compressor}.
          *
          * @param out the output stream
          * @param def the compressor ("deflater")
    @@ -98,7 +116,11 @@ public DeflaterOutputStream(OutputStream out,
          * buffer size.
          *
          * <p>The new output stream instance is created as if by invoking
    -     * the 4-argument constructor DeflaterOutputStream(out, def, size, false).
    +     * the 4-argument constructor {@code DeflaterOutputStream(out, def, size, false)}.
    +     * <p>
    +     * {@linkplain #close() Closing} this output stream
    +     * {@linkplain ##compressor-usage will not close} the given
    +     * {@linkplain Deflater compressor}.
          *
          * @param out the output stream
          * @param def the compressor ("deflater")
    @@ -112,6 +134,10 @@ public DeflaterOutputStream(OutputStream out, Deflater def, int size) {
         /**
          * Creates a new output stream with the specified compressor, flush
          * mode and a default buffer size.
    +     * <p>
    +     * {@linkplain #close() Closing} this output stream
    +     * {@linkplain ##compressor-usage will not close} the given
    +     * {@linkplain Deflater compressor}.
          *
          * @param out the output stream
          * @param def the compressor ("deflater")
    @@ -135,7 +161,11 @@ public DeflaterOutputStream(OutputStream out,
          * a default buffer size.
          *
          * <p>The new output stream instance is created as if by invoking
    -     * the 3-argument constructor DeflaterOutputStream(out, def, false).
    +     * the 3-argument constructor {@code DeflaterOutputStream(out, def, false)}.
    +     * <p>
    +     * {@linkplain #close() Closing} this output stream
    +     * {@linkplain ##compressor-usage will not close} the given
    +     * {@linkplain Deflater compressor}.
          *
          * @param out the output stream
          * @param def the compressor ("deflater")
    @@ -148,8 +178,12 @@ public DeflaterOutputStream(OutputStream out, Deflater def) {
     
     
         /**
    -     * Creates a new output stream with a default compressor, a default
    -     * buffer size and the specified flush mode.
    +     * Creates a new output stream and compressor with the
    +     * default compression level, a default buffer size and
    +     * the specified flush mode.
    +     * <p>
    +     * The compressor will be closed when this output stream
    +     * is {@linkplain #close() closed}.
          *
          * @param out the output stream
          * @param syncFlush
    @@ -166,10 +200,14 @@ public DeflaterOutputStream(OutputStream out, boolean syncFlush) {
         }
     
         /**
    -     * Creates a new output stream with a default compressor and buffer size.
    +     * Creates a new output stream and compressor with the
    +     * default compression level and a default buffer size.
          *
          * <p>The new output stream instance is created as if by invoking
    -     * the 2-argument constructor DeflaterOutputStream(out, false).
    +     * the 2-argument constructor {@code DeflaterOutputStream(out, false)}.
    +     * <p>
    +     * The compressor will be closed when this output stream
    +     * is {@linkplain #close() closed}.
          *
          * @param out the output stream
          */
    @@ -184,6 +222,7 @@ public DeflaterOutputStream(OutputStream out) {

    diff --git a/src/java.base/share/classes/java/util/zip/InflaterInputStream.java b/src/java.base/share/classes/java/util/zip/InflaterInputStream.java
    + *
    + * <h2 id="decompressor-usage">Decompressor Usage</h2>
    + * An {@code InflaterInputStream} created without
    + * specifying a {@linkplain Inflater decompressor} will create a decompressor
    + * at construction time, and close the decompressor when the input stream
    + * is {@linkplain #close closed}.
    + * <p>
    + * If a decompressor is specified when creating a {@code InflaterInputStream}, it is the
    + * responsibility of the caller to {@linkplain Inflater#close close} the
    + * decompressor after closing the input stream.
    + *
    + * @apiNote
    + * The {@link #close} method should be called to release resources used by this
    + * stream, either directly, or with the {@code try}-with-resources statement.
    + *
         /**
          * Creates a new input stream with the specified decompressor and
          * buffer size.
    +     * <p>
    +     * {@linkplain #close() Closing} this input stream
    +     * {@linkplain ##decompressor-usage will not close} the given
    +     * {@linkplain Inflater decompressor}.
    +     *
          * @param in the input stream
          * @param inf the decompressor ("inflater")
          * @param size the input buffer size
    @@ -94,6 +114,11 @@ public InflaterInputStream(InputStream in, Inflater inf, int size) {
         /**
          * Creates a new input stream with the specified decompressor and a
          * default buffer size.
    +     * <p>
    +     * {@linkplain #close() Closing} this input stream
    +     * {@linkplain ##decompressor-usage will not close} the given
    +     * {@linkplain Inflater decompressor}.
    +     *
          * @param in the input stream
          * @param inf the decompressor ("inflater")
          */
    @@ -104,7 +129,12 @@ public InflaterInputStream(InputStream in, Inflater inf) {
         boolean usesDefaultInflater = false;
     
         /**
    -     * Creates a new input stream with a default decompressor and buffer size.
    +     * Creates a new input stream and decompressor with a
    +     * default buffer size.
    +     * <p>
    +     * The decompressor will be closed when this input stream
    +     * is {@linkplain #close() closed}.
    +     *
          * @param in the input stream
          */
         public InflaterInputStream(InputStream in) {
    @@ -120,6 +150,7 @@ public InflaterInputStream(InputStream in) {

    diff --git a/src/java.base/share/classes/java/util/zip/InflaterOutputStream.java b/src/java.base/share/classes/java/util/zip/InflaterOutputStream.java
    + * <h2 id="decompressor-usage">Decompressor Usage</h2>
    + * An {@code InflaterOutputStream} created without
    + * specifying a {@linkplain Inflater decompressor} will create a decompressor
    + * at construction time, and close the decompressor when the output stream
    + * is {@linkplain #close closed}.
    + * <p>
    + * If a decompressor is specified when creating a {@code InflaterOutputStream}, it is the
    + * responsibility of the caller to {@linkplain Inflater#close close} the
    + * decompressor after closing the output stream.
    + *
    + * @apiNote
    + * The {@link #close} method should be called to release resources used by this
    + * stream, either directly, or with the {@code try}-with-resources statement.
    + *
         /**
    -     * Creates a new output stream with a default decompressor and buffer
    -     * size.
    +     * Creates a new output stream and decompressor with a
    +     * default buffer size.
    +     * <p>
    +     * The decompressor will be closed when this output stream
    +     * is {@linkplain #close() closed}.
          *
          * @param out output stream to write the uncompressed data to
          * @throws NullPointerException if {@code out} is null
    @@ -82,6 +99,10 @@ public InflaterOutputStream(OutputStream out) {
         /**
          * Creates a new output stream with the specified decompressor and a
          * default buffer size.
    +     * <p>
    +     * {@linkplain #close() Closing} this output stream
    +     * {@linkplain ##decompressor-usage will not close} the given
    +     * {@linkplain Inflater decompressor}.
          *
          * @param out output stream to write the uncompressed data to
          * @param infl decompressor ("inflater") for this stream
    @@ -94,6 +115,10 @@ public InflaterOutputStream(OutputStream out, Inflater infl) {
         /**
          * Creates a new output stream with the specified decompressor and
          * buffer size.
    +     * <p>
    +     * {@linkplain #close() Closing} this output stream
    +     * {@linkplain ##decompressor-usage will not close} the given
    +     * {@linkplain Inflater decompressor}.
          *
          * @param out output stream to write the uncompressed data to
          * @param infl decompressor ("inflater") for this stream
    @@ -123,6 +148,7 @@ public InflaterOutputStream(OutputStream out, Inflater infl, int bufLen) {


Comments
Moving to Approved.
08-04-2025

[~jpai] You can transition this CSR from draft to finalized.
07-04-2025