FileInputStream、FileOutputStream 类方法中都有一个 finalizer 方法,方法调用将导致JVM的垃圾收集暂停。参见JDK文档 FileInput/OutputStream/FileChannel cleanup should be improved JDK-8080225查看详情。
/**
* Cleans up the connection to the file, and ensures that the
* <code>close</code> method of this file output stream is
* called when there are no more references to this stream.
*
* @exception IOException if an I/O error occurs.
* @see java.io.FileInputStream#close()
*/
protected void finalize() throws IOException {
if (fd != null) {
if (fd == FileDescriptor.out || fd == FileDescriptor.err) {
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()
*/
close();
}
}
}
替换的建议
FileReader 和 FileWriter 在构造时也会初始化一个 FileInputStream 或 FileOutputStream。因此在调用 finalizer 方法时也会导致垃圾回收的问题。
所以应当替换相关的方法:
- 使用 Files.newInputStream(Paths.get(fileName)) 替代 new FileInputStream(fileName).
- 使用 Files.newOutputStream(Paths.get(fileName)) 替代 new FileOutputStream(fileName).
- 使用 Files.newBufferedReader(Paths.get(fileName)) 替代 new FileReader(fileName).
- 使用 Files.newBufferedWriter(Paths.get(fileName)) 替代 new FileWriter(fileName).
需要注意,java.nio API 不再抛出 FileNotFoundException 异常,而是抛出 NoSuchFileException 异常。如果在代码中有捕获文件未找到异常(FileNotFoundException)进行处理的逻辑,那么这部分代码需要做出调整。这两个异常都是IOException的子类,所以通过捕获IO异常就可以涵盖这两类异常。
JDK-8080225 内容
文件流如果没有完全关闭会触发一个最终的关闭处理。这会触发垃圾回收进行计划外的回收操作。文件流的清理关闭应该更高效,并且不会导致额外的垃圾会收操作。
使用虚引用机制,可以实现轻量级清理机制或其他合适的机制。
网友评论