8185582: Update Zip implementation to use Cleaner, not finalizers

Reviewed-by: plevart, rriggs, mchung
This commit is contained in:
Xueming Shen 2017-12-11 11:45:02 -08:00
parent 390de69601
commit 3b0e59e8d8
6 changed files with 648 additions and 192 deletions

View file

@ -66,13 +66,27 @@ package java.util.zip;
* }
* </pre></blockquote>
*
* @apiNote
* To release resources used by this {@code Inflater}, the {@link #end()} method
* should be called explicitly. Subclasses are responsible for the cleanup of resources
* acquired by the subclass. Subclasses that override {@link #finalize()} in order
* to perform cleanup should be modified to use alternative cleanup mechanisms such
* as {@link java.lang.ref.Cleaner} and remove the overriding {@code finalize} method.
*
* @implSpec
* If this {@code Inflater} has been subclassed and the {@code end} method has been
* overridden, the {@code end} method will be called by the finalization when the
* inflater is unreachable. But the subclasses should not depend on this specific
* implementation; the finalization is not reliable and the {@code finalize} method
* is deprecated to be removed.
*
* @see Deflater
* @author David Connelly
* @since 1.1
*
*/
public
class Inflater {
public class Inflater {
private final ZStreamRef zsRef;
private byte[] buf = defaultBuf;
@ -101,7 +115,7 @@ class Inflater {
* @param nowrap if true then support GZIP compatible compression
*/
public Inflater(boolean nowrap) {
zsRef = new ZStreamRef(init(nowrap));
this.zsRef = ZStreamRef.get(this, () -> init(nowrap), Inflater::end);
}
/**
@ -361,38 +375,37 @@ class Inflater {
/**
* Closes the decompressor and discards any unprocessed input.
*
* This method should be called when the decompressor is no longer
* being used, but will also be called automatically by the finalize()
* method. Once this method is called, the behavior of the Inflater
* object is undefined.
* being used. Once this method is called, the behavior of the
* Inflater 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 decompressor 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.
* @implSpec
* If this {@code Inflater} has been subclassed and the {@code end} method
* has been overridden, the {@code end} method will be called when the
* inflater is unreachable.
*
* @deprecated The {@code finalize} method has been deprecated and will be
* removed. It is implemented as a no-op. Subclasses that override
* {@code finalize} in order to perform cleanup should be modified to use
* alternative cleanup mechanisms and remove the overriding {@code finalize}
* method. The recommended cleanup for compressor is to explicitly call
* {@code end} method when it is no longer in use. If the {@code end} is
* not invoked explicitly the resource of the compressor will be released
* when the instance becomes unreachable,
*/
@Deprecated(since="9")
protected void finalize() {
end();
}
@Deprecated(since="9", forRemoval=true)
protected void finalize() {}
private void ensureOpen () {
assert Thread.holdsLock(zsRef);