--- old/test/jdk/java/io/FileOutputStream/UnreferencedFOSClosesFd.java 2018-10-11 12:56:43.174351331 -0400 +++ new/test/jdk/java/io/FileOutputStream/UnreferencedFOSClosesFd.java 2018-10-11 12:56:42.738349169 -0400 @@ -28,8 +28,7 @@ * @library /test/lib * @build jdk.test.lib.util.FileUtils UnreferencedFOSClosesFd * @bug 6524062 - * @summary Test to ensure that FOS.finalize() invokes the close() method as per - * the specification. + * @summary Test to ensure that the fd is closed if left unreferenced * @run main/othervm UnreferencedFOSClosesFd */ import java.io.File; @@ -54,15 +53,11 @@ public class UnreferencedFOSClosesFd { - 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). + * Subclass w/ no overrides; not close. + * Cleanup should be via the Cleaner. */ public static class StreamOverrides extends FileOutputStream { @@ -96,7 +91,7 @@ /** * Subclass overrides finalize and close. - * Cleanup should be via the Cleaner (not close). + * Cleanup should be via the Cleaner. */ public static class StreamOverridesFinalize extends StreamOverrides { @@ -105,14 +100,14 @@ } @SuppressWarnings({"deprecation","removal"}) - protected void finalize() throws IOException { + protected void finalize() throws IOException, Throwable { super.finalize(); } } /** * Subclass overrides finalize and close. - * Cleanup should be via AltFinalizer calling close(). + * Cleanup should be via the Cleaner. */ public static class StreamOverridesFinalizeClose extends StreamOverridesClose { @@ -121,7 +116,7 @@ } @SuppressWarnings({"deprecation","removal"}) - protected void finalize() throws IOException { + protected void finalize() throws IOException, Throwable { super.finalize(); } } @@ -131,8 +126,6 @@ */ public static void main(String argv[]) throws Exception { - - File inFile = new File(System.getProperty("test.dir", "."), FILE_NAME); inFile.createNewFile(); inFile.deleteOnExit(); @@ -143,15 +136,15 @@ long fdCount0 = getFdCount(); int failCount = 0; - failCount += test(new FileOutputStream(name), CleanupType.CLEANER); + failCount += test(new FileOutputStream(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); @@ -174,7 +167,7 @@ : -1L; } - private static int test(FileOutputStream fos, CleanupType cleanType) throws Exception { + private static int test(FileOutputStream fos) throws Exception { try { System.out.printf("%nTesting %s%n", fos.getClass().getName()); @@ -193,36 +186,19 @@ fdField.setAccessible(true); int ffd = fdField.getInt(fd); - Field altFinalizerField = FileOutputStream.class.getDeclaredField("altFinalizer"); - altFinalizerField.setAccessible(true); - Object altFinalizer = altFinalizerField.get(fos); - 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); - } - if (cleanup != null) { - WeakReference cleanupWeak = new WeakReference<>(cleanup, queue); - pending.add(cleanupWeak); - System.out.printf(" fdWeak: %s%n msWeak: %s%n cleanupWeak: %s%n", - fdWeak, msWeak, cleanupWeak); - } - if (altFinalizer != null) { - WeakReference altFinalizerWeak = new WeakReference<>(altFinalizer, queue); - pending.add(altFinalizerWeak); - System.out.printf(" fdWeak: %s%n msWeak: %s%n altFinalizerWeak: %s%n", - fdWeak, msWeak, altFinalizerWeak); + System.out.printf(" cleanup: %s, ffd: %d, cf: %s%n", cleanup, ffd, cleanupField); + if (cleanup == null) { + throw new RuntimeException("cleanup should not be null"); } + WeakReference cleanupWeak = new WeakReference<>(cleanup, queue); + pending.add(cleanupWeak); + System.out.printf(" fdWeak: %s%n msWeak: %s%n cleanupWeak: %s%n", + fdWeak, msWeak, cleanupWeak); + AtomicInteger closeCounter = fos instanceof StreamOverrides ? ((StreamOverrides) fos).closeCounter() : null; @@ -237,28 +213,16 @@ fos = null; fd = null; cleanup = null; - altFinalizer = null; System.gc(); // attempt to reclaim them } } Reference.reachabilityFence(fd); Reference.reachabilityFence(fos); Reference.reachabilityFence(cleanup); - Reference.reachabilityFence(altFinalizer); // Confirm the correct number of calls to close depending on the cleanup type - switch (cleanType) { - case CLEANER: - if (closeCounter != null && closeCounter.get() > 0) { - throw new RuntimeException("Close should not have been called: count: " - + closeCounter); - } - break; - case CLOSE: - if (closeCounter == null || closeCounter.get() == 0) { - throw new RuntimeException("Close should have been called: count: 0"); - } - break; + if (closeCounter != null && closeCounter.get() > 0) { + throw new RuntimeException("Close should not have been called: count: " + closeCounter); } } catch (Exception ex) { ex.printStackTrace(System.out);