# HG changeset patch
# User rriggs
# Date 1539701728 14400
# Node ID 0edbbc64393cc84b022afa92f983cb61f1a58313
# Parent 2d9f8845d0aef2dbd8a38c7d40707a71fe9d9d18
8192939: Remove Finalize methods from FileInputStream and FileOutputStream
Reviewed-by: alanb, iris, mchung
diff -r 2d9f8845d0ae -r 0edbbc64393c src/java.base/share/classes/java/io/FileInputStream.java
--- a/src/java.base/share/classes/java/io/FileInputStream.java Tue Oct 16 11:08:46 2018 -0400
+++ b/src/java.base/share/classes/java/io/FileInputStream.java Tue Oct 16 10:55:28 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1994, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -79,8 +79,6 @@
private volatile boolean closed;
- private final Object altFinalizer;
-
/**
* Creates a FileInputStream by
* opening a connection to an actual file,
@@ -155,10 +153,7 @@
fd.attach(this);
path = name;
open(name);
- altFinalizer = getFinalizer(this);
- if (altFinalizer == null) {
- FileCleanable.register(fd); // open set the fd, register the cleanup
- }
+ FileCleanable.register(fd); // open set the fd, register the cleanup
}
/**
@@ -195,7 +190,6 @@
}
fd = fdObj;
path = null;
- altFinalizer = null;
/*
* FileDescriptor is being shared by streams.
@@ -438,85 +432,4 @@
static {
initIDs();
}
-
- /**
- * Ensures that the {@link #close} method of this file input stream is
- * called when there are no more references to it.
- * The {@link #finalize} method does not call {@link #close} directly.
- *
- * @apiNote
- * To release resources used by this stream {@link #close} should be called
- * directly or by try-with-resources.
- *
- * @implSpec
- * If this FileInputStream has been subclassed and the {@link #close}
- * method has been overridden, the {@link #close} method will be
- * called when the FileInputStream is unreachable.
- * Otherwise, it is implementation specific how the resource cleanup described in
- * {@link #close} is performed.
- *
- * @deprecated The {@code finalize} method has been deprecated and will be removed.
- * 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.
- *
- * @exception IOException if an I/O error occurs.
- * @see java.io.FileInputStream#close()
- */
- @Deprecated(since="9", forRemoval = true)
- protected void finalize() throws IOException {
- }
-
- /*
- * Returns a finalizer object if the FIS needs a finalizer; otherwise null.
- * If the FIS has a close method; it needs an AltFinalizer.
- */
- private static Object getFinalizer(FileInputStream fis) {
- Class> clazz = fis.getClass();
- while (clazz != FileInputStream.class) {
- try {
- clazz.getDeclaredMethod("close");
- return new AltFinalizer(fis);
- } catch (NoSuchMethodException nsme) {
- // ignore
- }
- clazz = clazz.getSuperclass();
- }
- return null;
- }
- /**
- * Class to call {@code FileInputStream.close} when finalized.
- * If finalization of the stream is needed, an instance is created
- * in its constructor(s). When the set of instances
- * related to the stream is unreachable, the AltFinalizer performs
- * the needed call to the stream's {@code close} method.
- */
- static class AltFinalizer {
- private final FileInputStream fis;
-
- AltFinalizer(FileInputStream fis) {
- this.fis = fis;
- }
-
- @Override
- @SuppressWarnings("deprecation")
- protected final void finalize() {
- try {
- if ((fis.fd != null) && (fis.fd != FileDescriptor.in)) {
- /* if fd is shared, the references in FileDescriptor
- * will ensure that finalizer is only called when
- * safe to do so. All references using the fd have
- * become unreachable. We can call close()
- */
- fis.close();
- }
- } catch (IOException ioe) {
- // ignore
- }
- }
- }
}
diff -r 2d9f8845d0ae -r 0edbbc64393c src/java.base/share/classes/java/io/FileOutputStream.java
--- a/src/java.base/share/classes/java/io/FileOutputStream.java Tue Oct 16 11:08:46 2018 -0400
+++ b/src/java.base/share/classes/java/io/FileOutputStream.java Tue Oct 16 10:55:28 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1994, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -95,8 +95,6 @@
private volatile boolean closed;
- private final Object altFinalizer;
-
/**
* Creates a file output stream to write to the file with the
* specified name. A new FileDescriptor object is
@@ -235,10 +233,7 @@
this.path = name;
open(name, append);
- altFinalizer = getFinalizer(this);
- if (altFinalizer == null) {
- FileCleanable.register(fd); // open sets the fd, register the cleanup
- }
+ FileCleanable.register(fd); // open sets the fd, register the cleanup
}
/**
@@ -274,7 +269,6 @@
}
this.fd = fdObj;
this.path = null;
- this.altFinalizer = null;
fd.attach(this);
}
@@ -457,98 +451,9 @@
return fc;
}
- /**
- * Cleans up the connection to the file, and ensures that the
- * {@link #close} method of this file output stream is
- * called when there are no more references to this stream.
- * The {@link #finalize} method does not call {@link #close} directly.
- *
- * @apiNote
- * To release resources used by this stream {@link #close} should be called
- * directly or by try-with-resources.
- *
- * @implSpec
- * If this FileOutputStream has been subclassed and the {@link #close}
- * method has been overridden, the {@link #close} method will be
- * called when the FileOutputStream is unreachable.
- * Otherwise, it is implementation specific how the resource cleanup described in
- * {@link #close} is performed.
- *
- * @deprecated The {@code finalize} method has been deprecated and will be removed.
- * 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.
- *
- * @exception IOException if an I/O error occurs.
- * @see java.io.FileInputStream#close()
- */
- @Deprecated(since="9", forRemoval = true)
- protected void finalize() throws IOException {
- }
-
private static native void initIDs();
static {
initIDs();
}
-
- /*
- * Returns a finalizer object if the FOS needs a finalizer; otherwise null.
- * If the FOS has a close method; it needs an AltFinalizer.
- */
- private static Object getFinalizer(FileOutputStream fos) {
- Class> clazz = fos.getClass();
- while (clazz != FileOutputStream.class) {
- try {
- clazz.getDeclaredMethod("close");
- return new AltFinalizer(fos);
- } catch (NoSuchMethodException nsme) {
- // ignore
- }
- clazz = clazz.getSuperclass();
- }
- return null;
- }
-
- /**
- * Class to call {@code FileOutputStream.close} when finalized.
- * If finalization of the stream is needed, an instance is created
- * in its constructor(s). When the set of instances
- * related to the stream is unreachable, the AltFinalizer performs
- * the needed call to the stream's {@code close} method.
- */
- static class AltFinalizer {
- private final FileOutputStream fos;
-
- AltFinalizer(FileOutputStream fos) {
- this.fos = fos;
- }
-
- @Override
- @SuppressWarnings("deprecation")
- protected final void finalize() {
- try {
- if (fos.fd != null) {
- if (fos.fd == FileDescriptor.out || fos.fd == FileDescriptor.err) {
- // Subclass may override flush; otherwise it is no-op
- fos.flush();
- } else {
- /* if fd is shared, the references in FileDescriptor
- * will ensure that finalizer is only called when
- * safe to do so. All references using the fd have
- * become unreachable. We can call close()
- */
- fos.close();
- }
- }
- } catch (IOException ioe) {
- // ignore
- }
- }
- }
-
}
diff -r 2d9f8845d0ae -r 0edbbc64393c test/jdk/java/io/FileInputStream/UnreferencedFISClosesFd.java
--- a/test/jdk/java/io/FileInputStream/UnreferencedFISClosesFd.java Tue Oct 16 11:08:46 2018 -0400
+++ b/test/jdk/java/io/FileInputStream/UnreferencedFISClosesFd.java Tue Oct 16 10:55:28 2018 -0400
@@ -62,15 +62,11 @@
*/
public class UnreferencedFISClosesFd {
- enum CleanupType {
- CLOSE, // Cleanup is handled via calling close
- CLEANER} // Cleanup is handled via Cleaner
-
static final String FILE_NAME = "empty.txt";
/**
* Subclass w/ no overrides; not finalize or close.
- * Cleanup should be via the Cleaner (not close).
+ * Cleanup should be via the Cleaner.
*/
public static class StreamOverrides extends FileInputStream {
@@ -88,7 +84,7 @@
/**
* Subclass overrides close.
- * Cleanup should be via AltFinalizer calling close().
+ * Cleanup should be via the Cleaner.
*/
public static class StreamOverridesClose extends StreamOverrides {
@@ -104,7 +100,7 @@
/**
* Subclass overrides finalize.
- * Cleanup should be via the Cleaner (not close).
+ * Cleanup should be via the Cleaner.
*/
public static class StreamOverridesFinalize extends StreamOverrides {
@@ -113,7 +109,7 @@
}
@SuppressWarnings({"deprecation","removal"})
- protected void finalize() throws IOException {
+ protected void finalize() throws IOException, Throwable {
super.finalize();
}
}
@@ -129,7 +125,7 @@
}
@SuppressWarnings({"deprecation","removal"})
- protected void finalize() throws IOException {
+ protected void finalize() throws IOException, Throwable {
super.finalize();
}
}
@@ -149,15 +145,15 @@
long fdCount0 = getFdCount();
int failCount = 0;
- failCount += test(new FileInputStream(name), CleanupType.CLEANER);
+ failCount += test(new FileInputStream(name));
- failCount += test(new StreamOverrides(name), CleanupType.CLEANER);
+ failCount += test(new StreamOverrides(name));
- failCount += test(new StreamOverridesClose(name), CleanupType.CLOSE);
+ failCount += test(new StreamOverridesClose(name));
- failCount += test(new StreamOverridesFinalize(name), CleanupType.CLEANER);
+ failCount += test(new StreamOverridesFinalize(name));
- failCount += test(new StreamOverridesFinalizeClose(name), CleanupType.CLOSE);
+ failCount += test(new StreamOverridesFinalizeClose(name));
if (failCount > 0) {
throw new AssertionError("Failed test count: " + failCount);
@@ -180,7 +176,7 @@
: -1L;
}
- private static int test(FileInputStream fis, CleanupType cleanType) throws Exception {
+ private static int test(FileInputStream fis) throws Exception {
try {
System.out.printf("%nTesting %s%n", fis.getClass().getName());
@@ -199,35 +195,18 @@
fdField.setAccessible(true);
int ffd = fdField.getInt(fd);
- Field altFinalizerField = FileInputStream.class.getDeclaredField("altFinalizer");
- altFinalizerField.setAccessible(true);
- Object altFinalizer = altFinalizerField.get(fis);
- if ((altFinalizer != null) ^ (cleanType == CleanupType.CLOSE)) {
- throw new RuntimeException("Unexpected AltFinalizer: " + altFinalizer
- + ", for " + cleanType);
- }
-
Field cleanupField = FileDescriptor.class.getDeclaredField("cleanup");
cleanupField.setAccessible(true);
Object cleanup = cleanupField.get(fd);
- System.out.printf(" cleanup: %s, alt: %s, ffd: %d, cf: %s%n",
- cleanup, altFinalizer, ffd, cleanupField);
- if ((cleanup != null) ^ (cleanType == CleanupType.CLEANER)) {
- throw new Exception("unexpected cleanup: "
- + cleanup + ", for " + cleanType);
+ System.out.printf(" cleanup: %s, ffd: %d, cf: %s%n", cleanup, ffd, cleanupField);
+ if (cleanup == null) {
+ throw new RuntimeException("cleanup should not be null");
}
- if (cleanup != null) {
- WeakReference