< prev index next >

test/jdk/java/io/FileOutputStream/UnreferencedFOSClosesFd.java

Print this page
rev 52044 : 8192939: Remove Finalize methods from FileInputStream and FileOutputStream

*** 26,37 **** * @test * @modules java.base/java.io:open * @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. * @run main/othervm UnreferencedFOSClosesFd */ import java.io.File; import java.io.FileDescriptor; import java.io.FileNotFoundException; --- 26,36 ---- * @test * @modules java.base/java.io:open * @library /test/lib * @build jdk.test.lib.util.FileUtils UnreferencedFOSClosesFd * @bug 6524062 ! * @summary Test to ensure that the fd is closed if left unreferenced * @run main/othervm UnreferencedFOSClosesFd */ import java.io.File; import java.io.FileDescriptor; import java.io.FileNotFoundException;
*** 52,70 **** import jdk.test.lib.util.FileUtils; 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). */ public static class StreamOverrides extends FileOutputStream { protected final AtomicInteger closeCounter; --- 51,65 ---- import jdk.test.lib.util.FileUtils; public class UnreferencedFOSClosesFd { static final String FILE_NAME = "empty.txt"; /** ! * Subclass w/ no overrides; not close. ! * Cleanup should be via the Cleaner. */ public static class StreamOverrides extends FileOutputStream { protected final AtomicInteger closeCounter;
*** 94,159 **** } } /** * Subclass overrides finalize and close. ! * Cleanup should be via the Cleaner (not close). */ public static class StreamOverridesFinalize extends StreamOverrides { public StreamOverridesFinalize(String name) throws FileNotFoundException { super(name); } @SuppressWarnings({"deprecation","removal"}) ! protected void finalize() throws IOException { super.finalize(); } } /** * Subclass overrides finalize and close. ! * Cleanup should be via AltFinalizer calling close(). */ public static class StreamOverridesFinalizeClose extends StreamOverridesClose { public StreamOverridesFinalizeClose(String name) throws FileNotFoundException { super(name); } @SuppressWarnings({"deprecation","removal"}) ! protected void finalize() throws IOException { super.finalize(); } } /** * Main runs each test case and reports number of failures. */ public static void main(String argv[]) throws Exception { - - File inFile = new File(System.getProperty("test.dir", "."), FILE_NAME); inFile.createNewFile(); inFile.deleteOnExit(); String name = inFile.getPath(); FileUtils.listFileDescriptors(System.out); long fdCount0 = getFdCount(); int failCount = 0; ! failCount += test(new FileOutputStream(name), CleanupType.CLEANER); ! failCount += test(new StreamOverrides(name), CleanupType.CLEANER); ! failCount += test(new StreamOverridesClose(name), CleanupType.CLOSE); ! failCount += test(new StreamOverridesFinalize(name), CleanupType.CLEANER); ! failCount += test(new StreamOverridesFinalizeClose(name), CleanupType.CLOSE); if (failCount > 0) { throw new AssertionError("Failed test count: " + failCount); } --- 89,152 ---- } } /** * Subclass overrides finalize and close. ! * Cleanup should be via the Cleaner. */ public static class StreamOverridesFinalize extends StreamOverrides { public StreamOverridesFinalize(String name) throws FileNotFoundException { super(name); } @SuppressWarnings({"deprecation","removal"}) ! protected void finalize() throws IOException, Throwable { super.finalize(); } } /** * Subclass overrides finalize and close. ! * Cleanup should be via the Cleaner. */ public static class StreamOverridesFinalizeClose extends StreamOverridesClose { public StreamOverridesFinalizeClose(String name) throws FileNotFoundException { super(name); } @SuppressWarnings({"deprecation","removal"}) ! protected void finalize() throws IOException, Throwable { super.finalize(); } } /** * Main runs each test case and reports number of failures. */ public static void main(String argv[]) throws Exception { File inFile = new File(System.getProperty("test.dir", "."), FILE_NAME); inFile.createNewFile(); inFile.deleteOnExit(); String name = inFile.getPath(); FileUtils.listFileDescriptors(System.out); long fdCount0 = getFdCount(); int failCount = 0; ! failCount += test(new FileOutputStream(name)); ! failCount += test(new StreamOverrides(name)); ! failCount += test(new StreamOverridesClose(name)); ! failCount += test(new StreamOverridesFinalize(name)); ! failCount += test(new StreamOverridesFinalizeClose(name)); if (failCount > 0) { throw new AssertionError("Failed test count: " + failCount); }
*** 172,182 **** return (mxBean instanceof UnixOperatingSystemMXBean) ? ((UnixOperatingSystemMXBean) mxBean).getOpenFileDescriptorCount() : -1L; } ! private static int test(FileOutputStream fos, CleanupType cleanType) throws Exception { try { System.out.printf("%nTesting %s%n", fos.getClass().getName()); // Prepare to wait for FOS to be reclaimed --- 165,175 ---- return (mxBean instanceof UnixOperatingSystemMXBean) ? ((UnixOperatingSystemMXBean) mxBean).getOpenFileDescriptorCount() : -1L; } ! private static int test(FileOutputStream fos) throws Exception { try { System.out.printf("%nTesting %s%n", fos.getClass().getName()); // Prepare to wait for FOS to be reclaimed
*** 191,229 **** Field fdField = FileDescriptor.class.getDeclaredField("fd"); 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<Object> 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<Object> altFinalizerWeak = new WeakReference<>(altFinalizer, queue); - pending.add(altFinalizerWeak); - System.out.printf(" fdWeak: %s%n msWeak: %s%n altFinalizerWeak: %s%n", - fdWeak, msWeak, altFinalizerWeak); - } AtomicInteger closeCounter = fos instanceof StreamOverrides ? ((StreamOverrides) fos).closeCounter() : null; Reference<?> r; --- 184,205 ---- Field fdField = FileDescriptor.class.getDeclaredField("fd"); fdField.setAccessible(true); int ffd = fdField.getInt(fd); Field cleanupField = FileDescriptor.class.getDeclaredField("cleanup"); cleanupField.setAccessible(true); Object cleanup = cleanupField.get(fd); ! 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<Object> 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; Reference<?> r;
*** 235,266 **** pending.remove(r); } else { 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; } } catch (Exception ex) { ex.printStackTrace(System.out); return 1; } --- 211,230 ---- pending.remove(r); } else { fos = null; fd = null; cleanup = null; System.gc(); // attempt to reclaim them } } Reference.reachabilityFence(fd); Reference.reachabilityFence(fos); Reference.reachabilityFence(cleanup); // Confirm the correct number of calls to close depending on the cleanup type if (closeCounter != null && closeCounter.get() > 0) { ! throw new RuntimeException("Close should not have been called: count: " + closeCounter); } } catch (Exception ex) { ex.printStackTrace(System.out); return 1; }
< prev index next >