释放java文件句柄

Jam*_*ook 1 java io file handle gridgain

我们有一个用Java编写的相当大而复杂的应用程序,它运行在Gridgain包之上.我遇到的问题是这个应用程序将在每个请求开始前大约一天处理请求,导致java.nio.channels.ClosedByInterruptException类型的异常.

我的假设是应用程序没有释放文件句柄,并且在连续使用一天之后它用完了并且不​​能再继续处理请求(每个请求都需要从每个网格节点读取多个文件).我们已将大部分文件IO操作包装在诸如此类之类的类中

package com.vlc.edge;

import com.vlc.common.VlcRuntimeException;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;

public final class BufferedReaderImpl implements BufferedReader {
    private java.io.BufferedReader reader;

    public BufferedReaderImpl(final String source) {
        this(new File(source));
    }

    public BufferedReaderImpl(final File source) {
        try {
            reader = new java.io.BufferedReader(new FileReader(source));
        } catch (FileNotFoundException e) {
            throw new VlcRuntimeException(e);
        }
    }

    public BufferedReaderImpl(final Reader reader) {
        this.reader = new java.io.BufferedReader(reader);
    }

    public String readLine() {
        try {
            return reader.readLine();
        } catch (IOException e) {
            throw new VlcRuntimeException(e);
        }
    }

    public void close() {
        try {
            reader.close();
        } catch (IOException e) {
            throw new VlcRuntimeException(e);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我认为问题是这个设计没有明确释放文件句柄,我建议的解决方案是添加这样的finalize方法

    protected void finalize() throws Throwable
    {
        reader.close();
        super.finalize();   
    }
Run Code Online (Sandbox Code Playgroud)

这将明确地做到这一点.问题(最后)是否可能产生任何影响.像java.io.BufferedReader这样的类是否已经有一些机制来处理这类问题?

编辑:也非常感谢这里将是检查这是否实际上是问题的方法...即有没有办法查询正在运行的JVM并询问它的文件句柄分配?

cle*_*tus 12

不能依赖终结器进行调用.这对资源管理来说不是一个好方法.Java中的标准构造是:

InputStream in = null;
try {
  in = ...;
  // do stuff
} catch (IOException e) {
  // error
} finally {
  if (in != null) { try { in.close(); } catch (Exception e) { } }
  in = null;
}
Run Code Online (Sandbox Code Playgroud)

您可能希望将这些句柄包装在类中,但这不是一种强大的方法.

  • +1 ...但是如果你在'in'的初始化表达式中打开流,你可以摆脱'finally'块中的'null'测试.此外,最后对'in'的归零可能是多余的. (2认同)

fin*_*nnw 5

压倒一点没有意义finalize().如果句柄被垃圾收集并最终确定,那么实例也是如此java.io.BufferedReader,它将被关闭.

可能(根据规范)手柄是垃圾收集但未最终确定,但这不太可能.

您可以尝试使用PhantomReferences来清理未使用的文件句柄,但我的猜测是您的实例BufferedReaderImpl仍然从某处引用(例如,Map从文件名到打开句柄的值),这就是阻止它们被关闭的原因(在这种情况下)终结者无济于事.)