3

いくつかの大きな XML ファイルを読み取り、それらをデータベースに格納しています。800MB前後です。

多くのレコードを保存してから終了し、例外を発生させます。

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at java.util.IdentityHashMap.resize(Unknown Source)
    at java.util.IdentityHashMap.put(Unknown Source)

Memory Analyzer を使用して、次のような .hprof ファイルを作成しました。

  76,581 instances of "java.lang.String", loaded by "<system class loader>" occupy 1,04,34,45,504 (98.76%) bytes. 

Keywords
java.lang.String

値を取得するためのセッターとゲッターがあります。この問題を解決するにはどうすればよいですか。どんな助けでも感謝されます。

ここに画像の説明を入力

JREを使用してメモリを増やしました。。しかし、問題は解決しません

編集: XML ファイルを読み取るために scireumOpen を使用しています。

私が使用したコード例:

public void readD() throws Exception {

        XMLReader reader = new XMLReader();

        reader.addHandler("node", new NodeHandler() {

            @Override
            public void process(StructuredNode node) {
                try {



                    obj.setName(node
                            .queryString("name"));

                    save(obj);

                } catch (XPathExpressionException xPathExpressionException) {
                    xPathExpressionException.printStackTrace();
                } catch (Exception exception) {
                    exception.printStackTrace();
                }
            }
        });

        reader.parse(new FileInputStream(
                "C:/Users/some_file.xml"));

    }

    public void save(Reader obj) {

        try {
            EntityTransaction entityTransaction = em.getTransaction();
            entityTransaction.begin();
            Entity e1=new Entity;
            e1.setName(obj.getName());

            em.persist(e1);
            entityTransaction.commit();

        } catch (Exception exception) {
            exception.printStackTrace();
        }
    }
4

8 に答える 8

1

私の主なヒント: JPA コードをもう一度確認してください。できるだけ隔離する必要があります。

アイデアは、アノテーションで JAXB を使用することです。IdentityHashMap ( の==代わりにキーを使用equals) はめったにありません。JPA の可能性が高く、おそらく XML タグでしょうか? また、どの XML パーサーが使用されているかを確認することもできます (ファクトリ クラスを検査するか、Java SPI、サービス プロバイダー インターフェイスによってすべての XML パーサー プロバイダーを一覧表示します)。

たとえば、長さが 20 未満のすべての文字列など、文字列を共有できますMap<String, String>

private Map<String, String> sharedStrings = new HashMap<>();

private String shareString(String s) {
    if (s == null || s.length() > 20) {
        return s;
    }
    String t = sharedStrings.get(s);
    if (t == null) {
        t = s;
        sharedStrings.put(t, t);
    }
    return t;
}

public void setXxx(String xxx) {
    this.xxx = sharedString(xxx);
}

Bean 内の大きなテキストには圧縮 (GZip ストリーム) を使用できます。

于 2013-07-11T07:15:37.540 に答える
1

String使用している場合は使用しないでください。StringBufferまたはに置き換えてStringBuilderください。また、メモリを増やしてみてください。2048 で問題ないと思いますが、それでも問題が解決しない場合は、4096m に変更するか、6000m で試してください。

于 2013-07-15T05:50:57.060 に答える
1
  1. 最も明白な答えは、すでにここで述べたように、JVM メモリを増やすことです。java -XmxNN
  2. SAXParserTree の代わりに aを使用しDOMます (まだ行っていない場合)。これはアプリケーションの設計に依存するため、調査して、これが可能な戦略であるかどうかを確認する必要があります。
  3. コードを確認し、不要なオブジェクトをすべて削除して、GB から削除できるようにしてください。これには、参照が早期に削除されるように、変数をループ外ではなくループ内に移動することが含まれます。null不要になった後、未使用の要素を設定します。

コードを知らなくても、これは一般的なガイドラインにすぎません。

于 2013-07-11T06:43:11.843 に答える
0

投稿する前にコードを編集したか、正しくないコードを投稿したようです。修正してください。

まず、コードがコンパイルされません。

次に、Reader をsave関数に渡さないでください。Entity を作成して入力しprocess(StructuredNode node)、Reader ではなく Entity を渡して関数を保存します。

第三に、関数内で例外を正しく処理しsaveます。例外が発生した場合、トランザクションをロールバックします。

于 2013-07-11T07:58:18.733 に答える