ターゲット・システムが受け入れて処理するのをサポートするために、5 MBを超えるXMLドキュメントをより小さなチャンクに分割する必要があります。 XSLT v2ではサイズ別に分割されたXML文書がサポートされているように見えるので、Javaプログラムを作成することになりました。このプログラムは、文書が10 MB未満または10 MB未満の場合にうまく機能します。 32 MBのファイルが供給されると、プログラムは失敗します。プログラムはエージェントとして動作し、最大メモリーが25GBに設定されたJVMに接続されます。それにもかかわらず、我々は永続的にOOMヒープ空間エラーを見る。ヒープダンプファイルを生成することは、問題の容疑者1として、次のことを明らかに:これに基づきJava |サイズで分割されたXML | HashMapのパフォーマンスの問題| OOMヒープ・スペース・エラー
sun.misc.Launcher$AppClassLoader @ 0x1bb7ae098" occupies 156,512,240 (64.62%) bytes. The memory is accumulated in one instance of
、私はプログラムを検査開始し、潜在的にメモリの問題を引き起こす可能性がスポットを推定し、それがある[あなたがSYSOUT年代のいくつか無視することがこれらは私のデバッグセッション]のために添加したとおり
public static HashMap < Integer, String > splitPromotionItem(List promotionsItems, int promotionItemMaxSizeUoMNumericValue, int promotionItemMaxSize, String routingLocation, String docNum, XDNode messageHeader, XDNode promotionsData){
HashMap < Integer, String > promotionItemMap = new HashMap < Integer, String >();
int totalSubMessage = 1;
String promotionsItemsData = "";
int promotionsItemsSize = 0;
String promotionsItemsDataTemp = "";
int i = 0;
int q = 1;
do {
promotionsItemsSize = promotionsItemsSize + ((XDNode) promotionsItems.get(i)).flatten().getBytes().length;
promotionsItemsData = promotionsItemsData + ((XDNode) promotionsItems.get(i)).flatten();
if (promotionsItemsSize > (promotionItemMaxSize * 1024 * 1024)) {
System.out.println("Inside First If: " + promotionsItems.size() + ": " + q++);
promotionsItemsSize = promotionsItemsSize - ((XDNode) promotionsItems.get(i)).flatten().getBytes().length;
promotionsItemsData = promotionsItemsDataTemp;
promotionItemMap.put(totalSubMessage++, promotionsItemsData);
if (i != (promotionsItems.size() - 1)) {
System.out.println("Inside Second If: " + promotionsItems.size());
i--;
promotionsItemsSize = 0;
promotionsItemsData = "";
} else {
System.out.println("Inside Second Else: " + promotionsItems.size());
promotionsItemsSize = ((XDNode) promotionsItems.get(i)).flatten().getBytes().length;
promotionsItemsData = ((XDNode) promotionsItems.get(i)).flatten();
}
}
if (promotionsItemsSize < (promotionItemMaxSize * 1024 * 1024) && (i) == (promotionsItems.size() - 1)) {
promotionItemMap.put(totalSubMessage++, promotionsItemsData);
}
i++;
promotionsItemsDataTemp = promotionsItemsData;
} while (i < promotionsItems.size());
return promotionItemMap;
}
プログラムは、まず、後の各エントリを介してその反復関数に供給されるハッシュマップに格納されている小さなチャンクに大きなXML文書を分割するように見えますマップしてファイルに書き込みます。ファイルの名前と内部の要素の1つは、分割バッチ内のファイルのインデックスと、簡単に認識できるように合計分割数を保持します。
最初の考えでは、コードを次のように改訂しました。小さなXMLチャンクをHashMapに集める代わりに、ファイルに直接書き込んでください。これはまた、すべての小さなチャンクがディスクに保存された後に、それらを再度開いて、ファイルインデックスとファイル総数とファイル名の内容を更新する必要があります。
これを処理する方法はありますか?助けてください。
注:JVMは毎日大量のデータを処理し、次の起動オプションを負い、私たちは、XSLTプロセサとしてサクソン使用:
-Djavax.xml.transform.TransformerFactory=net.sf.saxon.TransformerFactoryImpl -Xmx15360M -Xrs -XX:GCTimeRatio=5 -XX:+PrintGCDetails -Xloggc:<location> -XX:MinHeapFreeRatio=25 -XX:MaxHeapFreeRatio=60
アップデート29112017
クラスの使用XDNodeとその機能flattenは、プロセスフローをシームレスに実行するためにエージェントをJVMにプラグインできるように、iWayが提供するAPIでプログラムを拡張した結果です。
XDNodeは、XMLツリーの単一要素です。完全な文書はXDNodeのツリーです。 XDNodeクラスとツリーは、高速な解析と検索、およびアプリケーションでの簡単な操作のために設計されています。メソッドは、XDNodeツリーと標準JDOMツリーの間で変換するために利用できます。すべてのサーバー操作はXDNodeのツリーで実行されます。
flatten()は、XMLドキュメント全体をStringとして返します。
分割操作がエレメント/ SalonApps /プロモーション/ PromotionData/PromotionItemで実行されます。ここでは
は、XML文書は次のようになります方法の例です。 PromotionItemが発生するたびに反復処理を行い、上記のコードのように反復されたチャンクを一時変数に格納します。また、パッケージングとファイル書き込み操作を実行する必要性を判断するために、各反復の開始時に5 MB [クラスの冒頭で定義された制限]を超えるサイズがあるかどうかを確認します。サイズが小さくなると、反復はさらに収集されて保存されます。ドキュメントのヘッダーセクション[/ SalonApps/Promotion/MessageHeader]は、スプリットメッセージのインデックスをバッチで反映するように変更されたMessageIDの値と、2番目と3番目の場所でのバッチの合計カウントを使用して、各分割ドキュメントに追加されます値はハイフンで区切られます。
XSLT v1およびv2のみをサポートしています。 XSLT v1またはv2を使用してXML文書をそのサイズで分割することができれば、それは素晴らしいことです。
XDNodeとは何ですか? XDNodeのflatten()操作は何をしますか? XML文書の構造は何ですか?どのようにそれを分割しようとしていますか?これらの質問に対する答えを知らなくても、私たちはあなたのコードを理解することができますか? –
@MichaelKay、遅れのために私の謝罪。私は気分が悪かった。私はあなたに示された項目に対処するための明確さを加えました。ありがとうございました。 – Srii