2011-07-17 16 views
3

メモリエラーが発生しているため、JVM引数を設定してJSFアプリケーションのメモリ消費量を調整しようとしています。java.lang.OutOfMemoryError:Javaのヒープスペース - メモリの節約方法

JVM引数 ...私はメモリヒープを増やし、一日二回、サーバーを再起動することができるよ、それは解決策ではありません。

-XX:+UseConcMarkSweepGC 
-XX:+UseParNewGC 
-XX:+CMSClassUnloadingEnabled 
-XX:+CMSParallelRemarkEnabled 
-XX:CMSInitiatingOccupancyFraction=30 
-XX:+CMSIncrementalMode 
-XX:+CMSIncrementalPacing 
-XX:ParallelCMSThreads=2 
-XX:+UseCMSCompactAtFullCollection 
-XX:+DisableExplicitGC 
-XX:MaxHeapFreeRatio=70 
-XX:MinHeapFreeRatio=40 
-XX:MaxTenuringThreshold=30 
-XX:NewSize=512m 
-XX:MaxNewSize=512m 
-XX:SurvivorRatio=2 
-XX:PermSize=150m 
-Xms1024m 
-Xmx1024m 

すべてが正常に動作するよう、テニュア空間は0MBで、エデン空間は連続的にクリアされますが、生存空間はまだ成長しており、限界に達するとオブジェクトはテナント空間に移動され、決して解放されません。そして、アプリケーションの実行の半日後、私はメモリ不足のエラーを取得します。だから私はTomcatサーバーの自動再起動をスケジュールする必要があります。

enter image description here

だから私は、そのメモリの消費は、(一日あたりのデータベースで数千人の動きについて)このような小さなAPPLには高すぎるので、私のアプリケーションでは、いくつかの問題がなければならない、と思います。

Bean.java

/* save datalist */ 
public void save() 
{ 
    session = DaoSF.getSessionFactory.openSession(); 
    try 
    { 
    Dao.save(dataList); 
    } 
    catch (Exception e) {...} 
    finally 
    { 
    session.close(); 
    } 
} 

public static void save(List<? extends Object> dataList) 
{ 
    for (Object dataItem : dataList) 
    { 
    save(dataItem); 
    } 
} 
public static void save(Object dataItem) 
{ 
    try 
    { 
    Transaction tx = session.beginTransaction(); 
    session.save(dataItem); 
    tx.commit(); 
    } 
    catch(Exception e) {....} 
} 

DaoSF.java

01 Dao.java

私のコードの一部があります

保存されたオブジェクトがメモリに残らないようにオブジェクトをデータベースに保存(更新、削除)する際のベストプラクティスは何ですか?

+0

?これはOracleセッションですか?特にDAOではメソッドが静的であるため? – home

+0

ところで:セッションはDAOの中にカプセル化されるべきだと思う。 – home

+0

わかりませんが、メモリリークが発生するため、静的なものを避けるのは常に良い方法だと聞いています –

答えて

3

これを試してください。まだ完全ではありませんが、Daoの静的セッション属性を取り除かなければならないと思います。 hibernate docs::

実装者がスレッドセーフであることを意図していません。代わりに、各スレッド/トランザクションはSessionFactoryから独自のインスタンスを取得する必要があります。

は、基礎となる永続性メカニズムのいずれかの知識を持っていないように、また、ダオ自体の内部セッションを取得することができますが、私はそれほど変更したくありませんでした。あなたはセッションオブジェクトを格納しない

Bean.java

/* save datalist */ 
public void save() { 
    Session session = nlul; 
    try { 
     session = DaoSF.getSessionFactory.openSession(); 
     /* one instance per call, 
     * ready for garbage collection after leaving this method 
     */ 
     Dao mydao = new Dao(session); 
     mydao.save(dataList); 
    } catch (Exception e) {... 
    } finally { 
     if (sessioN != null) 
      session.close(); 
    } 
} 

Dao.java

private Session mysession = null; 

public Dao(Session mysession) { 
    this.mysession = mysession; 
} 

public void save(List<? extends Object> dataList) { 
    for (Object dataItem : dataList) { 
     save(dataItem); 
    } 
} 

public void save(Object dataItem) { 
    try { 
     Transaction tx = session.beginTransaction(); 
     this.mysession.save(dataItem); 
     tx.commit(); 
    } 
    catch(Exception e) {....} 
} 
+0

ありがとう、私はまずコードを書く前に考えなければなりません:) – gaffcz

+0

@ gaffcz:No prob。正直言って、これが最終的にあなたの問題を解決するかどうかはわかりません。しかし、OOM例外をさらに調べる前に、この問題を解決する必要があります。 – home

+0

ありがとうございます!私はDaoSF.java simillaryを書き直し、クラスを使用せず、クラスのインスタンスを使用しました。また、私は静的メソッド(例えば時間計算など)をいくつか持っていますが、同じ方法でそれらを書き直そうとするか、あるいはJ2EEアプリケーションの静的メソッドを持つのが普通ですか? – gaffcz

2

"PermGen:Out of Memory"がある場合、それはエデン、サバイバー、テナントスペースにはあまり関係しません。

Permgenの "Non-Heap"の部分は、-XX:PermSize = 150mに関連しています。より大きなサイズを試してみてください。

それ以外の場合は、JSP /サーブレットコンパイラ/クラスローダ/スプリングでメモリリークが発生している可能性があります。これは、クラスが割り当てられたメモリを占有する可能性があります。

+0

ありがとう、私は前にPermSizeを増やそうとしましたが、画像上に見られるように、ヒープ以外の部分はOKです。 – gaffcz

+0

+1 - permgen空間に関する観測のため。 –

+0

@jaime - 例外メッセージに "PermGen:out of memory"と表示された場合、あなたはpermgenメモリを使い果たしています。あなたは監視グラフを誤解しています。 –

4

データベースの保存/削除/更新に関して、メモリの問題が直接関係することはほとんどありません。 PermGenスペースは、一般的に、任意のユーザー・レベルのオブジェクトに使用されていません。それは、このようなクラス定義、JVMの状態の内部ビットなどの割り当てを解除しないで決してに意図されているもの、のために使用されている。

があった場合データオブジェクトをどのように管理しているかに問題がある場合は、OutOfMemoryErrorにヒープスペースが残っていないとの不満があります。しかし、あなたの質問に答えるためには、オブジェクトは、スコープを離れた後に実行される次のガベージコレクションパスでガベージコレクションされます(つまり、どこにも参照がないことを意味します)。 OutOfMemoryError問題が発生していないので、あなたは既にこの罰金を処理していると思います。

PermGen領域外の場合は、アプリケーションが多数のライブラリを使用している可能性があります。悲しいことに、この問題を解決する唯一の方法は、PermGenサイズを大きくすることである、のような:

-XX:PermSize=256m

それは通常賢明であるように、これは、本質的に、あなたのアプリケーションに利用可能なヒープ・スペースの量を減少することに注意してください同様に、対応する量によって、あなたの総JVMのメモリ割り当てを増やすために:

-Xmx1130m

は、試してみて、それはあなたのために任意のより良い動作するかどうかを確認します。

+0

大変申し訳ありません、java.lang.OutOfMemoryError:Javaヒープスペースです。 permSizeを変更してヒープサイズを上げようとしましたが、sulutionではありません。後でTomcatサーバーを後で再起動することができるので、余分な時間がかかります... – gaffcz

関連する問題