2009-10-22 22 views
1

因此,我有一個應用程序正在gridgain上運行,並且在開始行爲有趣之前在12-24小時的壓力測試中相當成功。經過這一段時間的應用程序會突然開始回覆到與異常java.nio.channels.ClosedByInterruptException所有查詢(完整的堆棧跟蹤爲http://pastie.org/664717Java Gridgain應用程序在經過1天的壓力測試後開始失敗

編輯以@stephenc反饋使用從失敗的方法是(

public static com.vlc.edge.FileChannel createChannel(final File file) { 
    FileChannel channel = null; 
    try { 
    channel = new FileInputStream(file).getChannel(); 
    channel.position(0); 
    final com.vlc.edge.FileChannel fileChannel = new FileChannelImpl(channel); 
    channel = null; 
    return fileChannel; 
    } catch (FileNotFoundException e) { 
    throw new VlcRuntimeException("Failed to open file: " + file, e); 
    } catch (IOException e) { 
    throw new VlcRuntimeException(e); 
    } finally { 
    if (channel != null) { 
     try { 
     channel.close(); 
     } catch (IOException e){ 
     // noop 
     LOGGER.error("There was a problem closing the file: " + file); 
     } 
    } 
    } 
} 

和調用函數正確地關閉對象

private void fillContactBuffer(final File signFile) { 
    contactBuffer = ByteBuffer.allocate((int) signFile.length()); 
    final FileChannel channel = FileUtils.createChannel(signFile); 
    try { 
     channel.read(contactBuffer); 
    } finally { 
     channel.close(); 
    } 
    contactBuffer.rewind(); 
} 

的應用基本上用作分佈式文件解析器所以它做了很多這些類型的操作(通常會爲每個節點的每個查詢打開大約10個這樣的通道)。看起來,在一段時間後,它停止了能夠打開文件,我無法解釋爲什麼會發生這種情況,並會非常感謝任何人可以告訴我什麼可能導致這種情況,以及如何跟蹤跟蹤它下來並修復它。如果它可能與文件句柄耗盡有關,我很樂意聽到有關發現肯定的任何提示......即查詢運行中的JVM或使用Linux命令行工具查找有關當前處理的更多信息。

更新:我已經使用命令行工具來查詢lsof的輸出被並一直沒能看到任何證據證明文件句柄正在舉行開放......在網格中每個節點都有一個非常我可以看到,隨着上述代碼的執行,打開的文件的穩定配置文件會變化...但它總是返回到穩定數量的打開文件。

與此相關的問題:Freeing java file handles

回答

2

有一對夫婦的場景中文件句柄可能不會被關閉:

  1. 有可能是打開文件的一些其他的代碼。
  2. 有可能是調用createChannel(...),並且不調用fillContactBuffer(...)
  3. 如果channel.position(0)拋出一個異常代碼中的一些其他位,該通道不會被關閉。解決方法是重新安排代碼,以便在try區塊中使用以下語句。

    channel.position(0); 
    return new FileChannelImpl(channel); 
    

編輯:縱觀堆棧跟蹤,似乎這兩種方法在不同的代碼庫。我會指責createChannel方法。即使它不是問題的根源,它也可能有漏洞。它需要在內部finally子句中確保在發生異常時關閉通道。

像這樣的東西應該做的伎倆。請注意,您需要確保finally塊在成功時不會關閉通道!

public static com.vlc.edge.FileChannel createChannel(final File file) { 
    final FileChannel channel = null; 
    try { 
     channel = new FileInputStream(file).getChannel(); 
     channel.position(0); 
     FileChannel res = new FileChannelImpl(channel); 
     channel = null; 
     return res; 
    } catch (FileNotFoundException e) { 
     throw new VlcRuntimeException("Failed to open file: " + file, e); 
    } catch (IOException e) { 
     throw new VlcRuntimeException(e); 
    } finally { 
     if (channel != null) { 
      try { 
       channel.close(); 
      } catch (...) { 
       ... 
      } 
     } 
    } 
} 

隨訪晚得多

由於文件句柄泄漏已被淘汰的可能的原因,我的下一個理論將是在服務器端使用Thread.interrupt()實際上中斷自己的線程。一些低級I/O調用通過拋出異常來響應中斷,並且在這裏拋出根異常看起來就像一個這樣的異常。

這並不能解釋爲什麼這種情況正在發生,但是我想說,這是服務器端框架試圖解決過載或死鎖問題。