5

私は C++ プログラマーであり、現在のアプリケーションのいくつかにとって神が送る JPA を見つけた後、Java をいじっています。私は大学以来 Java に触れていませんが、ヒープ領域が不足しています。jdbc/jpa/lucene のそれほど深刻ではないテストの主要部分として以下のコードを使用していますが、ランダムな OutOfMemory 例外が発生し続けます。

        EntityManager em = emf.createEntityManager();
        Query q = em.createQuery("select p from Product p" +
            " where p.productid = :productid");
        Connection con = DriverManager.getConnection("connection string");
        Statement st = con.createStatement();

        IndexWriter writer = new IndexWriter("c:\\temp\\lucene", new StandardAnalyzer(), IndexWriter.MaxFieldLength.LIMITED);

        ResultSet rs = st.executeQuery("select productid from product order by productid");
        while (rs.next()) {
            int productid = rs.getInt("PRODUCTID");
            q.setParameter("productid", productid);
            Product p = (Product)q.getSingleResult();

            writer.addDocument(createDocument(p));
        }

        writer.commit();
        writer.optimize();
        writer.close();

        st.close();
        con.close();

createDocument のすべてを投稿するわけではありませんが、新しい org.apache.lucene.document.Document をインスタンス化し、add(new Field...) などを介してフィールドを追加するだけです。合計で約 50 のフィールドがあり、ほとんどが短いものです。文字列 (<32 文字) の長さ。

私の新人で、私がやっている(またはしていない)完全に愚かなことはありますか?

Java メモリ管理と GC のくすぐりに関するベスト プラクティスはありますか?

4

6 に答える 6

3

明らかに場違いなものは見当たりません。-Xmx n非常に大規模なデータベースを使用している場合は、JVM呼び出しのオプションを使用してヒープサイズを増やしてみてください。これは通常、最善の解決策ではありません。ワーキングセットのサイズが実際にデフォルトのヒープサイズよりも大きいことがわかっている場合にのみ、これを使用してください。

複雑なデータ構造を使用していますか?オブジェクト間に循環参照がある場合は、ガベージコレクターが到達不能なオブジェクトをクリーンアップできないようにしている可能性があります。手書きのデータ構造がある場合は、サイズ変数をデクリメントするようなことをするのではなく、削除されたオブジェクトへの参照を明示的に無効にするようにしてください。

于 2008-10-20T01:21:11.857 に答える
2

SAPメモリアナライザを試してください。

https://www.sdn.sap.com/irj/sdn/wiki?path=/display/Java/Java+Memory+Analysis

これにより、ダンプファイルが読み込まれ、メモリを占有しているものを調査できます。

于 2008-10-20T01:28:17.723 に答える
2

上手...

Javaとデータベースに関する長年の経験( postgresSQL mysql oracleの違いの例>)は、この作業を行う際に使用するJDBCドライバーに問題が頻繁に発生することを教えてくれました。

24時間年中無休でデータベースに接続したままにする必要のあるコードが1つあり、ドライバーのメモリリークが原因で、JVMは常にある時点でチョークします。そのため、スローされた特定の例外をキャッチし、接続を切断して再接続し、必死になってJVMを再起動するなど、ますます抜本的なアクションを実行するコードを作成しましたが、問題の状況をクリアするために何も機能していません。それを書かなければならないのはなんと苦痛なのでしょうが、DBMSベンダーが問題を引き起こさない新しいJDBCドライバーを発表するまではうまくいきました...念のため、実際にはコードをそのままにしておきました。

...だから、それはあなたがしていることではないかもしれません。

ガベージコレクターを呼び出すことは私が使用した戦略の1つでしたが、メトリックはそれがほとんど役に立たないことを示したことに注意してください。

さらに、明確ではないかもしれませんが、ResultSetsは、データベースエンジン自体への継続的な接続を維持します。多くの場合(明示的に設定されていない限り)、読んでいるだけでも双方向です。また、一部のJDBCドライバーでは、単方向接続を要求できますが、嘘をついて双方向接続を返します。これに注意してください!

したがって、ResultSetオブジェクトを他のオブジェクトにアンロードして値を保持し、ResultSetオブジェクト自体をできるだけ早くドロップすることをお勧めします。

幸運を。RTIII

于 2008-10-20T01:41:24.733 に答える
2

Permanent Generation のスペースが不足している可能性があります。スタック トレースに java.lang.OutOfMemoryError: PermGen のようなものが含まれているかどうかを確認します

jvm の次のパラメーターを使用して、この世代のスペースを増やすことができます: -XX:MaxPermSize=128m

パーマネント ジェネレーションのオブジェクトは、ガベージ コレクション中に考慮されません。Sun のこのページを見て、ガベージ コレクションと JVM のさまざまな世代のオブジェクトについて詳しく学んでください。

于 2008-10-22T09:41:59.067 に答える
0

結果セットにはいくつのアイテムがありますか?十分なレコードがある場合は、作成しているすべてのドキュメントへの参照を保持するライターにaddDocumentを実行しているときにガベージコレクションが行われないため、すべてのメモリを使い果たします。

于 2008-10-20T01:38:30.213 に答える
0

Java はいくつかの異なるメモリ プールを保持しており、それらのいずれかが不足すると、恐ろしい OutOfMermoryException が発生する可能性があります。オペレーティング システムによるメモリ割り当ての問題も、OOM として現れることがあります。

詳細なスタック トレース (または、アプリケーションのディレクトリ内のエラー ダンプ ファイル) が表示され、問題に関するさらなる手がかりが得られる可能性があります。

適切なプロファイラー (最近の Sun Java 6 JDK に同梱されている JVisualVM で十分でしょう) を使用すると、さまざまなプールをすべて監視し、どのプールが不足しているかを確認できます。

于 2008-10-22T09:29:09.407 に答える