< prev index next >

src/java.base/share/classes/java/util/zip/Deflater.java

Print this page

        

@@ -23,10 +23,15 @@
  * questions.
  */
 
 package java.util.zip;
 
+import jdk.internal.ref.CleanerFactory;
+
+import java.lang.ref.Cleaner;
+import java.lang.ref.Reference;
+
 /**
  * This class provides support for general purpose compression using the
  * popular ZLIB compression library. The ZLIB compression library was
  * initially developed as part of the PNG graphics standard and is not
  * protected by patents. It is fully described in the specifications at

@@ -65,18 +70,32 @@
  * } catch (java.util.zip.DataFormatException ex) {
  *     // handle
  * }
  * </pre></blockquote>
  *
+ * <p>
+ * @apiNote
+ * In earlier versions the {@link Object#finalize} method was overridden and
+ * specified to call the {@code end} method to close the {@code deflater} and
+ * release the resource when the instance becomes unreachable.
+ * The {@code finalize} method is no longer defined. The recommended cleanup
+ * for compressor is to explicitly call {@code end} method when it is no
+ * longer in use.
+ *
+ * @implNote
+ * The resource of the compressor will be released when the instance becomes
+ * phantom-reachable, if the {@code end} is not invoked explicitly.
+ * <p>
+ *
  * @see         Inflater
  * @author      David Connelly
  * @since 1.1
  */
 public
 class Deflater {
 
-    private final ZStreamRef zsRef;
+    private final Cleaner.LongCleanableResource zsRef;
     private byte[] buf = new byte[0];
     private int off, len;
     private int level, strategy;
     private boolean setParams;
     private boolean finish, finished;

@@ -167,11 +186,15 @@
      * @param nowrap if true then use GZIP compatible compression
      */
     public Deflater(int level, boolean nowrap) {
         this.level = level;
         this.strategy = DEFAULT_STRATEGY;
-        this.zsRef = new ZStreamRef(init(level, DEFAULT_STRATEGY, nowrap));
+        this.zsRef = CleanerFactory
+            .cleaner()
+            .createLongResource(this,
+                                () -> init(level, DEFAULT_STRATEGY, nowrap),
+                                Deflater::end);
     }
 
     /**
      * Creates a new compressor using the specified compression level.
      * Compressed data will be generated in ZLIB format.

@@ -240,11 +263,12 @@
         if (off < 0 || len < 0 || off > b.length - len) {
             throw new ArrayIndexOutOfBoundsException();
         }
         synchronized (zsRef) {
             ensureOpen();
-            setDictionary(zsRef.address(), b, off, len);
+            setDictionary(zsRef.value(), b, off, len);
+            Reference.reachabilityFence(this);
         }
     }
 
     /**
      * Sets preset dictionary for compression. A preset dictionary is used

@@ -443,11 +467,12 @@
         synchronized (zsRef) {
             ensureOpen();
             if (flush == NO_FLUSH || flush == SYNC_FLUSH ||
                 flush == FULL_FLUSH) {
                 int thisLen = this.len;
-                int n = deflateBytes(zsRef.address(), b, off, len, flush);
+                int n = deflateBytes(zsRef.value(), b, off, len, flush);
+                Reference.reachabilityFence(this);
                 bytesWritten += n;
                 bytesRead += (thisLen - this.len);
                 return n;
             }
             throw new IllegalArgumentException();

@@ -459,11 +484,13 @@
      * @return the ADLER-32 value of the uncompressed data
      */
     public int getAdler() {
         synchronized (zsRef) {
             ensureOpen();
-            return getAdler(zsRef.address());
+            int adler = getAdler(zsRef.value());
+            Reference.reachabilityFence(this);
+            return adler;
         }
     }
 
     /**
      * Returns the total number of uncompressed bytes input so far.

@@ -522,58 +549,41 @@
      * Keeps current compression level and strategy settings.
      */
     public void reset() {
         synchronized (zsRef) {
             ensureOpen();
-            reset(zsRef.address());
+            reset(zsRef.value());
+            Reference.reachabilityFence(this);
             finish = false;
             finished = false;
             off = len = 0;
             bytesRead = bytesWritten = 0;
         }
     }
 
     /**
      * Closes the compressor and discards any unprocessed input.
+     *
      * This method should be called when the compressor is no longer
-     * being used, but will also be called automatically by the
-     * finalize() method. Once this method is called, the behavior
-     * of the Deflater object is undefined.
+     * being used. Once this method is called, the behavior of the
+     * Deflater object is undefined.
      */
     public void end() {
         synchronized (zsRef) {
-            long addr = zsRef.address();
-            zsRef.clear();
-            if (addr != 0) {
-                end(addr);
+            zsRef.clean();
                 buf = null;
             }
         }
-    }
-
-    /**
-     * Closes the compressor when garbage is collected.
-     *
-     * @deprecated The {@code finalize} method has been deprecated.
-     *     Subclasses that override {@code finalize} in order to perform cleanup
-     *     should be modified to use alternative cleanup mechanisms and
-     *     to remove the overriding {@code finalize} method.
-     *     When overriding the {@code finalize} method, its implementation must explicitly
-     *     ensure that {@code super.finalize()} is invoked as described in {@link Object#finalize}.
-     *     See the specification for {@link Object#finalize()} for further
-     *     information about migration options.
-     */
-    @Deprecated(since="9")
-    protected void finalize() {
-        end();
-    }
 
     private void ensureOpen() {
         assert Thread.holdsLock(zsRef);
-        if (zsRef.address() == 0)
+        try {
+            zsRef.value();
+        } catch (IllegalStateException e) {
             throw new NullPointerException("Deflater has been closed");
     }
+    }
 
     private static native void initIDs();
     private static native long init(int level, int strategy, boolean nowrap);
     private static native void setDictionary(long addr, byte[] b, int off, int len);
     private native int deflateBytes(long addr, byte[] b, int off, int len,
< prev index next >