--- old/src/java.base/share/classes/java/util/zip/Deflater.java 2017-10-31 23:27:35.188589249 +0100 +++ new/src/java.base/share/classes/java/util/zip/Deflater.java 2017-10-31 23:27:35.068591293 +0100 @@ -25,6 +25,11 @@ 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 @@ -67,6 +72,20 @@ * } * * + *

+ * @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. + *

+ * * @see Inflater * @author David Connelly * @since 1.1 @@ -74,7 +93,7 @@ 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; @@ -169,7 +188,11 @@ 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); } /** @@ -242,7 +265,8 @@ } synchronized (zsRef) { ensureOpen(); - setDictionary(zsRef.address(), b, off, len); + setDictionary(zsRef.value(), b, off, len); + Reference.reachabilityFence(this); } } @@ -445,7 +469,8 @@ 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; @@ -461,7 +486,9 @@ public int getAdler() { synchronized (zsRef) { ensureOpen(); - return getAdler(zsRef.address()); + int adler = getAdler(zsRef.value()); + Reference.reachabilityFence(this); + return adler; } } @@ -524,7 +551,8 @@ public void reset() { synchronized (zsRef) { ensureOpen(); - reset(zsRef.address()); + reset(zsRef.value()); + Reference.reachabilityFence(this); finish = false; finished = false; off = len = 0; @@ -534,43 +562,25 @@ /** * 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); - buf = null; - } + 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();