2009-10-22 91 views
1

我们有一个用Java编写的相当大且复杂的应用程序,它运行在Gridgain包的顶部。我遇到的问题是,在每个请求开始之前大约一天,此应用程序将在那里处理请求,导致java.nio.channels.ClosedByInterruptException类型的异常。释放java文件句柄

我的假设是应用程序没有释放文件句柄,并且在连续使用一天后,它将用完并且不能再继续处理请求(每个请求需要从每个网格节点读取多个文件)。我们包裹我们的大多数文件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); 
     } 
    } 
} 

我认为问题是,这样的设计并没有明确释放文件句柄,我所提出的解决方案是增加一个finalize方法,像这样

protected void finalize() throws Throwable 
    { 
     reader.close(); 
     super.finalize(); 
    } 

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

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

回答

5

重写finalize()没什么意义。如果句柄正在垃圾收集和最终确定,那么java.io.BufferedReader的实例也会被关闭。

有可能(根据规范)手柄正在垃圾收集,但没有最终确定,但这不太可能。

你可以尝试使用PhantomReference s到清理未使用的文件句柄,但我的猜测是,你的BufferedReaderImpl情况下仍从某处引用(例如值在Map从文件名,打开的句柄),这是什么阻止他们从关闭(在这种情况下,终结器将无济于事)

+0

啊,这是一个非常好的观点,而且我正在寻找的答案的类型...将仔细检查并回来接受 – 2009-10-22 05:14:31

+0

是您的问题的解决方案? – dlinsin 2009-11-02 12:20:21

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

您可能想要将这些句柄包装到类中,但这不是一种可靠的方法。

+1

+1 ...但是如果你在'in'的初始化表达式中打开流,你可以在'finally'中去掉'null'测试'块。而且,最后的'in'归零可能是多余的。 – 2009-10-22 04:23:15

+1

但是那么in的范围将以try块和catch块结束,或者finally块不会变量! – user12458 2014-02-05 18:31:54

1

Java规范说,不能保证'finalize()'将被执行。您的代码必须自己关闭FileReader

相关问题