-
Type:
CSR
-
Resolution: Approved
-
Priority:
P3
-
None
-
Component/s: core-libs
-
behavioral
-
low
-
-
Java API
-
SE
Summary
To replace the finalizer mechanism with java.lang.ref.Cleaner to close the object java.util.zip.ZipFile/Inflater/Deflater, and cleanup/release its underlying native resources when the object is no longer reachable.
Problem
The finalization mechanism has a history of usage and performnace issues, it is desirable the j.u.zip implementation to migrate away from its use of finalizer to the newly introduced java.lang.ref.Cleaner.
Solution
-
To mark the overridden finalize() method of ZipFile/Deflater/Inflater class as "@Deprecated(, forRemoval=true)" and implement it with an empty body (to leverage the VM feature that vm does not put an object into the finalization process if its finalize() has an empty-body-ed implementation). The new implementation uses Cleaner to do the resource cleanup when the object has become unreachable, with the exception when the ZipFile/Inflater/Deflater has been subclassed and its corresponding close()/end() method has been overridden. In this case, the finalization mechanism is used to do the cleanup, and for behavioral compatibility, the corresponding close()/end() in subclass method will be called when the ZipFile/Inflater/Deflater object is unreachable.
-
To update the specification of the end() method (for both Deflater and Inflater) to remove the requirement that the end() "will be called by the finalizer() automatically".
-
To add additional @apiNote in class spec and @implSpec in finalize() method spec to clarify (a) the recommended approach to cleanup the resource after use, and (b) there is no guarantee that the close()/end() method will be called directly by finalize(), though the method in subclass will be called after the object is unreachable, via an implementation specific mechanism, for behavioral compatibility.
http://cr.openjdk.java.net/~sherman/8185582/webrev
Specification
src/java.base/share/classes/java/util/zip/Deflater.java
[adding class spec]
+ * @apiNote
+ * To release resources used by this {@code Deflater}, 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 Deflater} has been subclassed and the {@code end} method has been
+ * overridden, the {@code end} method will be called by the finalization when the
+ * deflater 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.
+ *
[updating end() spec]
/**
* 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() {...}
[updating finalize() spec]
/**
* 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();
- }
+ * @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 to 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", forRemoval=true)
+ protected void finalize() {}
src/java.base/share/classes/java/util/zip/Inflater.java
[adding class spec]
+ * @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.
+ *
[updating end() spec]
/**
* 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() {
[updating finalize() spec]
/**
* 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.
- */
- @Deprecated(since="9")
- protected void finalize() {
- end();
- }
+ * @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", forRemoval=true)
+ protected void finalize() {}
src/java.base/share/classes/java/util/zip/ZipFile.java
[adding class spec]
+ * @apiNote
+ * To release resources used by this {@code ZipFile}, the {@link #close()} method
+ * should be called explicitly or by try-with-resources. 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 ZipFile} has been subclassed and the {@code close} method has
+ * been overridden, the {@code close} method will be called by the finalization
+ * when {@code ZipFile} 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.
+ *
[updating finalize() spec]
/**
* Ensures that the system resources held by this ZipFile object are
* released when there are no more references to it.
*
- * <p>
- * Since the time when GC would invoke this method is undetermined,
- * it is strongly recommended that applications invoke the {@code close}
- * method as soon they have finished accessing this {@code ZipFile}.
- * This will prevent holding up system resources for an undetermined
- * length of time.
- *
- * @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 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 to remove the overriding
+ * {@code finalize} method. The recommended cleanup for ZipFile object
+ * is to explicitly invoke {@code close} method when it is no longer in
+ * use, or use try-with-resources. If the {@code close} is not invoked
+ * explicitly the resources held by this object will be released when
+ * the instance becomes unreachable.
+ *
* @throws IOException if an I/O error has occurred
- * @see java.util.zip.ZipFile#close()
*/
- @Deprecated(since="9")
- protected void finalize() throws IOException {}
- csr of
-
JDK-8185582 Update Zip implementation to use Cleaner, not finalizers
-
- Resolved
-
- relates to
-
JDK-8187325 Relax FileInputStream/FileOutputStream requirement to use finalize
-
- Closed
-