2009-09-02 5 views
1

メモリに画像をロードしようとしていますが、他の画像がロードされているのでメモリの問題が発生する可能性があります。これらの画像には、可視かどうかを指示する「可視」フィールドがあります。可視性にかかわらず、私は速い読み込みのためにそれらを記憶に残します(それらが再び見えるようになったとき)。この「try-error-clean -retry」のケースを処理する最良の方法は何ですか?

しかし、私はそれらの多くをメモリに持っているので、私は新しいイメージを読み込もうとしています。もし私がメモリの問題に遭遇したら、見えないイメージを解放して、やり直してください。今、これまでのところ、私はこのかなり醜い使用しています(何らかの理由で、間違ったが、私は確信しています)コードの一部:

try { 
    image = GraphicsUtilities.loadImage(filePath); 
} catch (OutOfMemoryError e) { 
    removeHiddenImageReferences(); 
    try { 
     image = GraphicsUtilities.loadImage(filePath); 
    } catch (OutOfMemoryError ee) { 
     ee.printStackTrace(); 
     JOptionPane.showMessageDialog(parent, 
      "There is not enought memory to load this image", 
      "Not enough memory", JOptionPane.WARNING_MESSAGE); 
    } 
} 

私の質問は、どのように私はこのような場合を処理する必要がありますか?私は例外をキャッチし、catch節の中で例外をキャッチするのが悪いと感じています。

答えて

4

"catch"句の全体的な点は、例外の原因を処理することです。この場合、メモリを使い果たしてメモリを解放し、エラーを伝播する前にもう一度再試行できるようにすることを選択します。完全に合理的だと思われます。あなたは、構文矛盾した任意の数の方法でそれを書き換えて、catch節の中にコードを書くことを避けることができますが、なぜ気にしますか?これはあなたの意図をはっきりと表しています。

ただし、2番目のケースで例外を再現する(またはそれをキャッチしないでください)と、完全なメモリを処理するためのよりグローバルな例外ハンドラがあることは意味があります。これは議論の余地があります。あなたが他のOutOfMemoryの状況を本当に期待していない場合は、(ほぼ)常にそれが妥当であるというシナリオの近くでそれを処理してください。

1

リトライロジックがスローされるだけでなく、条件に結びつくようにwhileループを導入します。

int tryCount = 2; 
while (tryCount > 0) { 
    try { 
    image = GraphicsUtilities.loadImage(filePath); 
    } catch (OutOfMemoryError e) { 
    removeHiddenImageReferences(); 
    tryCount--; 
    } 
} 
if(tryCount <= 0) { 
     JOptionPane.showMessageDialog(parent, 
      "There is not enought memory to load this image", 
      "Not enough memory", JOptionPane.WARNING_MESSAGE); 
} 

この例では、スタックトレースをミス、しかし、あなたは(ちょうどMessageDialogに識別子を含めるか、このチェックが行われている場所ログ)メモリ不足しているので、この時点でそれはそれは重要ではありません。

+0

答えに感謝します。私は徐々にメモリを解放していた(一度に1つの隠し画像をリリースするかもしれませんが)私の例では一度だけこれが上に少しあると思うので解放します。 –

2

1つのオプションは、2つのメソッドに分割することです。あなたは、内部的にTryLoadImageを呼び出すLoadImageを呼び出します。

public void TryLoadImage(string filePath){ 
    bool b = false; 

    try{ 
      image = GraphicsUtilities.loadImage(filePath); 
      bool b = true; 
    } 
    catch(OutOfMemoryError){ 
      // Log notfication of file the was too big perhaps? so in the future you could 
      // optimize this? 
    } 
} 

public void LoadImage(string filePath, bool clearReferences){ 

     if(!TryLoadImage(string filePath))  
     { 
      removeHiddenImageReferences(); 
      if(!TryLoadImage(string filePath)){ 
        // Log error 
        JOptionPane.showMessageDialog .... 
      } 
     } 
} 
+0

良い選択肢...実際には、私は自分の答えを別に表現していたはずです。私はそれをコード化する方法(あなたの答えは本当に良いです)に他ならないだけでなく、自分のデザインに "悪い"ものが書かれているかどうかに興味がありました。私の簡単な例では、私の解決策が書いて維持するのが最も簡単かもしれないと思っています。 –

+0

私はあなたがそれをやっているやり方が悪いと思っています。完全に捨てるのではなくOut of Manaの例外を取得すると必ず何かを記録して、パフォーマンスを監視することができます。 –

3

OutOfMemoryError sは個々Threadsに固有ではないので、これは、厳しいものです。つまり、現在のThreadでは、プロセスのメモリの大部分を占めるイメージをロードしていますが、Threadが実際にOutOfMemoryErrorをトリガーするプロセスを実行している可能性があります。このケースをインプロセスで処理する必要がある場合は、よりグローバルなOOMEマネージャーのAdam Wrightの考え方を検討してください。

編集:あなたはOOMEをトリガーする前に、リスナーが警告を受けることができるように、メモリ警告システムの設定について

This article会談。これにより、予防措置を取ることができ、衰弱しているOOMEからシステムを救うことができます。あなたのコメントを読んで、私は後世のためにここにリンクを掲示しています。

+0

hmはそれを考えていませんでした。しかし、このメソッドが呼び出された時の私のケースではありがたいことに、EDTだけが実行されるので、私は良いです。しかし、私は一般的なケースでメモをする必要があります。 –

1

SoftReferenceを使用したことがありますか?ここでコードを変更する必要はありませんが、アプリケーションが他のことをしている場合には状況をよりスケーラブルにし、他の場所でメモリが足りなくなった場合にはこれらの画像を投棄する意思があります。

-1

あなたは

removeHiddenImageReferences(); 

最初に呼び出すことができます。それで、あなたはtry/catchを1つだけ必要とします。あなたがremoveHiddenImageReferences()を知っていない限り、最適化は使用されません(何百万ものオブジェクトを扱っている場合など)。とにかくメモリが足りなくなってしまうのは大変なことです。

+0

全体のポイントはremoveHiddenImageReferences()を呼び出さない。もし私がする必要はありません。私は可能な限り多くの画像をメモリに保存し、必要なときにのみメモリを解放したいと思っています –

+0

申し訳ありませんが、私はちょうどあなたのコードを読んで、 – Shizzmo

関連する問題