、我々は我々のアプリケーションの一つでヒープ領域が不足してJVMで問題が発生しています。プロファイラでヒープダンプを見るなど、私はこれの原因を探していましたが、今はかなり固執しています。Hibernateは、SessionFactoryObjectFactoryとOutOfMemoryErrorが発生:私は仕事のJavaヒープ領域
まず、問題のシステムについて少し:それは、組織についての記録を保持するために、春と休止状態を使用して、Javaアプリケーションです。システムは、このタイプのデータを担当する政府機関から組織に関するデータを取得するために使用される一連のWebサービスクライアントで構成されています。また、システムは、組織に関する最初の時間情報が、それはローカル・リレーショナル・データベースに保存されている要求され、これは検索のために使用されるように、Webサービスの呼び出しのためのキャッシュとして動作する、そのようなデータをローカルデータベースを保持します次の要求のデータのHibernateは、このデータベースとの通信に使用されます。
問題は、先に示したように、一定期間後に、アプリケーションはOutOfMemoryErrorが発生してクラッシュし始めるということです:Javaのヒープ領域。私はEclipse + MATを使ってヒープダンプを調べ、割り当てられたメモリの約85%を占めるHibernateのSessionFactoryObjectFactoryであることを確認しました(すべてがメモリを保持していました)。私は、この中にどのようなタイプのオブジェクトが保持されているかを正確に特定するのは少し難しいことを発見しました。トップレベルには、org.hibernate.impl.SessionFactoryObjectFactoryを含むGlassfish WebappClassLoaderがあります。これにはorg.hibernate.util.FastHashMapが含まれ、これにはjava.util.HashMapが含まれます。これには、HashMapエントリ、org.hibernate.impl.SessionFactoryImpl、およびStringを含む多数のエントリが含まれています。 HashMapエントリには、同じ3つのオブジェクト(HashMapエントリ、SessionFactoryImpl、およびString)が含まれています。この構造は、何度も繰り返されます。 SessionFactoryImplsは、文字列とハッシュマップの数が含まれているオブジェクトの数、最も顕著なorg.hibernate.persister.entity.SingleTableEntityPersisterが含まれています。文字列の中には、ドメインオブジェクトの変数を参照するものと、SQL文を含むものがあります。
このオブジェクトは余分なメモリを占有していたようでした(ダンプファイルは800MBでしたが、うち650MBはSessionFactoryObjectFactoryが占有していました)ので、オブジェクトのロードとアンロードのログを有効にして、システムに関する情報(他のシステムからのWebサービス呼び出しによる)。私がここで気づいたのは、オブジェクトを読み込むためのメッセージがたくさんありましたが、アンロードされたオブジェクト(ライブラリオブジェクトをアンロードしていたオブジェクトのみ)はほとんどありませんでした。これは、オブジェクト(いったん組織)がメモリにロードされると、決してアンロードされないことを意味します。これは、時間の経過とともにシステムがメモリ不足になることを意味します。 (これはログで発見されたものに基づいて公正な仮定ですか?)
その後、私はこの原因を発見しようとしたが、これは多くの困難でした。 Hibernateによって読み込まれたオブジェクトは、セッションが存続する限り存続するため、SpringのHibernateDaoSupport#getSession()への呼び出しをHibernateDaoSupport#getSessionFactory()。getCurrentSession()に置き換えることによって、セッションの処理方法を変更しようとしました。これは問題には何の影響もありませんでした。また、問題のDaoメソッドのfinallyブロックで、getCurrentSession()。flush()と.clear()の呼び出しを追加しようとしました。 (Daoメソッドにはすべて@Transactionalというアノテーションが付けられているため、セッションは@ Transactionalメソッド内でのみ有効で、getCurrentSession()(?)を呼び出すときには、メソッドに対する連続呼び出しで異なるセッションを取得する必要があります)
これで、私はチェックするために他の領域を考え出すことになるとかなり止まってしまいました。誰に見えるか、何を探すべきかについてのアイデアやポインタがありますか?
ヒープダンプは、org.hibernate.impl.SessionFactoryImplのインスタンスがたくさんあることを示しました。これは期待どおりですか? (私は、SessionFactoryのインスタンスが1つだけ、またはいくつかのトップがあるべきだと思っていたでしょう。)
お返事ありがとうございます。
よろしく、
Tobb
編集:私は、私が実際に問題を解決するためにmanangedまし
思う:
は、それは他のオブジェクトへの依存性がで扱われたそのように判明しましたwebservice-classesが問題でした。これは、Webサービスクラスのコンストラクタで新しいClassPathXmlApplicationContext(...)を呼び出すことで解決されました。これは、(主にHibernateのSessionFactoryImpl)再びアンロードされなかった各要求(または少なくとも各セッション)に対して多くのオブジェクトがロードされるようになりました。私はwebservice-classesを変更して、依存関係を注入し、これまでのところプロファイラーを使って見たものを形成して、複数のSessionFactoryImplオブジェクトの問題を解決しました。
GlassFish 2.xからGlassFish 3.xへのアップグレードによって問題が悪化している可能性があります。これは、webservice-classのインスタンス化方法の違いかもしれません。
私もちょうど質問自体ではなく、答えにこの問題に解決策が追加される場合があります
代わりに静的な工場に、私は 'ClassPathXmlApplicationContext'ができ' close'-方法を持っていると思いますこの問題を回避するために呼び出されます。 – Tobb