< 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 >