23

IBM iSeries システムで、Java プログラムを実行しています。これは、すべて社内で開発された Web サーバー コンポーネントを備えたアプリケーション サーバーです。32 ビットまたは 64 ビットの J9 JVM (IBM Technology for Java) で実行すると、メモリ リークの症状が発生します。

iSeries クラシック JVM、複数の Sun/Oracle JVM、および Linux JVM でこのソフトウェアを実行しても、問題は発生しないことに注意してください。ええと、私は自分のウェブサイトで作業している間、妻のエントリーレベルのラップトップで同じソフトウェアを一度に何週間も実行したままにしておくことが日常的にあります.

アプリケーションを構成せず (基本的にはメッセージング システムと Web サーバーのみ)、プレーン バニラ システムをアイドル状態のままにしておくと、ヒープはゆっくりと成長し続け、時間の経過とともにより多くのメモリが割り当てられ、各 GC サイクルは前のレベルまでかなり集めています。パターンは、GC スイープが常にヒープを以前の GC レベルに減らすことを除いて、問題のない JVM の場合とまったく同じです。

ここに画像の説明を入力

しかし、安定化後に起動時に JVM システム ダンプを取得し、割り当てられたヒープが大幅に増加した後に後続のダンプを取得すると、差分比較は、起動時よりも 1 週間実行した後、到達可能なオブジェクトがなくなったことを示します。1週間後の最新のものは、6つの追加のクラスがロードされ、それに明確に関連するいくつかのオブジェクトを示しています。すべての生きているオブジェクトの徹底的なレビューは、私が予想外に飛び出したものは何も示していません.

スループット最適化ガベージ コレクタと世代同時並行ガベージ コレクタを試しました。

そのため、ジョブのヒープ サイズによると、リークしているように見え、ヒープ ダンプによると、何もリークしていません。

呼び出される JNI メソッドはありません (コア JVM の一部として実行されるネイティブ コードを除く)。それは間違いなくヒープが成長していることです。コンソールで JMX Bean を使用して報告されるだけでなく、IBM WRKJVMJOB 情報でもそれを明確に確認できます。ログファイル。

これまでのところ、JVisualVM などの JMX ツールを使用してアクティブな JVM に接続することはできません。適切に構成されている場合はリッスン ソケットが作成されますが、明らかにプロトコル レベルで接続が拒否されるためです (TCP/IP スタックは受け入れられた接続を示しますが、 JVM がバウンスします)。

私は当惑し、次にどこへ行けばよいか途方に暮れています。

編集:明確にするために。これらの結果はすべて、インストルメント化されていない JVM を使用したものです。これは、この JVM への JMX アクセスを取得できないためです (IBM と協力して取り組んでいます)。

EDIT 2011-11-16 19:27: Soft/Weak/PhantomReference カウントの特定のカウントを含む 1823 GC サイクルにわたる GC アクティビティ レポートを取得できました。これらの数字が暴走する兆候はありません。ただし、小さなオブジェクトの保有スペースは大幅に増加しています (大きなオブジェクトの保有スペースは空です)。9M から 36M に成長しました。

4

3 に答える 3

5

私のプログラムで不注意なメモリの浪費 (リークはありませんが) を排除し、ワークロードに合わせて GC をより適切に調整したことで、暴走したメモリの使用を許容できるレベルまで下げました。

ただし、その過程で、AS/400 (別名 iSeries、Systemi、i5 など) で使用される IBM J9 JVM には 1336 バイト/分のリークがあり、合計で 2 MB/日になることを実証しました。このリークは、「1 行」のテスト プログラムからアプリケーション サーバーに至るまで、さまざまなプログラムで観察できます。

1 行のテスト プログラムは次のとおりです。

public class ZMemoryLeak2
extends Object
{

static public synchronized void main(String... args) {
    try { ZMemoryLeak2.class.wait(0); } catch(InterruptedException thr) { System.exit(0); }
    }

}

また、JMX API を介してメモリ使用量を監視する以外は何も行わなかった別のテスト プログラムは、1336 B が正確に 1 分間隔でリークされ、再利用されないことを最終的に示しました (まあ、2 週間の実行後に再利用されませんでした)。OP 注: 実際には、JVM のバリエーションごとにわずかに異なる量でした。

更新 2012-04-02 : これは、数週間前に IBM によってバグとして受け入れられました。Java 5 で実際に発見され、パッチが適用されたのは昨年の中頃で、Java 6 のパッチは来週か 2 週間以内に利用可能になる予定です。

于 2011-12-07T20:38:32.997 に答える
4

素晴らしい質問です。コメントのいくつかを答えに変えたいと思いました。

  1. アイドル状態のシステムはメモリの観点から成長するとおっしゃいました。これは重要な情報です。オブジェクトの帯域幅を引き起こしている内部のスケジュールされたジョブ(自動化、タイマーなど)または外部のプロセス監視のいずれかがあります。グラフが影響を受けるかどうかを確認するために、監視をオフにすることを検討します。これは、どのオブジェクトが問題の一部であるかを把握するのに役立つ場合があります。

  2. オブジェクトに負荷がかかっているときは、ある程度のオブジェクト帯域幅があると思います。最終的な問題は、IBM JVMが他のJVMと同様にメモリの断片化を処理していないことかもしれませんが、これには驚いています。私は彼らと協力して、他のさまざまなGCオプションを試して、これに対処する方法を確認します。大量のメモリ操作を実行するテストサーバーを作成し、メモリ使用量が数日で増加するかどうかを確認する場合、これは簡単にシミュレートできると思います。これは、IBMJVMから移行する時期であることを示している可能性があります。繰り返しますが、これは私を驚かせるでしょうが、あなたの言うことが真実であり、オブジェクトの数やサイズが増えていない場合は...

  3. さまざまなメモリセクションのグラフを見ていきます。旧世代の宇宙が上下し、生存者が着実に滴り落ちるのを見ているのではないかと思います。オブジェクトの数が変化していないことが事実である場合、@ Stephenは、それらの内部サイズまたはそれが機能している他の何かについて正しい必要があります。おそらく、オブジェクトアカウンティングは、何らかの理由でそれらすべてを報告できていません。

  4. メモリタブのgcJMXボタンがより完全なスイープを実行することがわかりました。System.gc()それはあなたが試したものを使用することと同等でなければなりません。参考までに。

  5. GCロギング出力をオンにして、パターンが表示されるかどうかを確認するとよいでしょう:http: //christiansons.net/mike/blog/2008/12/java-garbage-collection-logging/およびhttp://java。 sun.com/developer/technicalArticles/Programming/GCPortal/

  6. 監視や内部自動化を変更せずに、サーバーのトランザクションスループットを向上させることができる可能性はありますか?メモリグラフの傾きが変化するのを見ると、トランザクションベースであることがわかります。そうでなければ、あなたの問題は他の場所にあります。繰り返しますが、これは、問題を引き起こしている可能性のあるオブジェクトを見つけるのに役立ちます。

ここに何かが役立つことを願っています。

于 2011-11-16T20:52:07.163 に答える
3

WeakReference考えられる理由の1つは、または同様のものを使用して実装されたキャッシュにオブジェクトが蓄積されていることです。シナリオは次のようになります。

  • グラフに表示されるGCサイクルは新しいスペースのコレクションであり、参照が壊れることはありません。そのため、キャッシュは増え続け、より多くのヒープスペースを使用します。

  • スナップショットを作成すると、完全なGCが実行され、(おそらく)参照が中断され、キャッシュされたオブジェクトが解放されます。

(「たぶん」に注意してください。この説明が水を保持しているかどうかはわかりません...)


別の考えられる説明は、アプリケーションに同じ数のオブジェクトがありますが、それらのいくつかはより大きいということです。たとえば、より大きなサイズで再割り当てし続けるプリミティブ型の配列がある場合があります。または、StringBuilder/StringBufferは成長を続けます。または(状況によっては)成長し続けるArrayListなど。


あなたが知っている、あなたはここでファントムを追いかけている可能性があります。システムダンプが真実を伝えており、ストレージリークがまったくない可能性があります。ヒープサイズを、実際のメモリリークが比較的迅速にOOMEを引き起こす可能性が高いポイントまで減らすことで、その理論をテストできます。そのようにOOMEを引き起こすことができなかった場合、私はこれを興味深い好奇心として書き留める傾向があります...そして実際の問題に移ります。

于 2011-11-16T03:08:01.990 に答える