2009-10-22 234 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