2016-11-14 4 views
1

特定のJavaクラスが使用しているメモリの量を(おおまかに)測定する軽量な方法があるかどうかは疑問です。のは、次のインターフェイスを考えてみましょう:特定のメソッドでのJavaオブジェクトの割り当て/割り当て解除の監視

interface MyAction <T, R> { 
    R execute(T item); 
} 

私が使用しているどのくらいのメモリフィールドとしてインスタンス化されるすべてのオブジェクトまたは実行オーバーライドメソッド内の変数として知っていただきたいと思います。もちろん、他のメソッドを呼び出すときに作成されたすべてのオブジェクトも考慮する必要があります。 は、私の知る限り最良の選択肢(このreplyを読んで)理解できるようになりますと:新しい、NEWARRAY、anewarray、multianewarray:次の手順のいずれかの前に、ASMのフレームワークと場所フックを通して

  • パッチJVMバイトコード。

  • JNI関数テーブルを変更して、すべてのJNI呼び出し(存在する場合)をインターセプトします。

  • すべてのVMObjectAllocイベントを代行受信します。

これらの3つのステップはすべての可能な割り当てをカバーしますが、オブジェクトの割り当てを追跡するための適切な方法があるかどうかはわかりませんでした。

私は、オブジェクトのgc割り当て解除を通知し、すべてのObjectFreeイベント(タグ付きオブジェクトのみ)を傍受するためにfinalizeメソッドのバイトコードにパッチを適用します。私はこれがすべての割り当て解除イベントをカバーしないことを確信しています。したがって、この問題を解決するのに役立つ既知のテクニックがありますか?

ありがとうございます。

+1

ちょうど不思議なことに、なぜあなたはそのすべてを知りたいのですか? – GhostCat

+0

いくつかの手動解析を行う場合は、ヒープダンプを作成し、Eclipse MATのようなツールを使用して分析することができます。それ以外では 'finalize()'を使って割り振りを追跡できるはずですが、vmは必要のないオブジェクトが確定することを保証しないので、私はそれを考慮しません。実際には、ライブスレッドから到達できないオブジェクトはガーベッジコレクション/デリバリのために認識できないものの、実行時にはかなりのコストがかかる可能性があり、既存のヒープダンプアナライザはこれを正確に実行します。 – Thomas

+0

正直言って、実行時にそのような情報を知りたいのは、内部処理のためにすでに独自のメモリ管理を持っているシステムを最適化しようとしているからです。 MyActionをオーバーライドするコードは制御されていないため、リアルタイムの統計に基づいてオンザフライでチューニングすると、より良いメモリマネージャが得られるはずです。もちろん、私はまだゲームがキャンドルの価値があるかどうかを評価しています。 @トーマスはい、間違いなくfinalize()は信頼できません。 –

答えて

0

割り当てられたメモリの量ではなく、割り当てられたすべてのオブジェクトに関心があるので、より簡単な方法を使用することができます。

与えられたスレッドによって割り当てられたメモリの累積量を返すメソッドThreadMXBean.getThreadAllocatedBytesがあります。 execute以降を呼び出す前に、カウンタを記録するだけです。差異は、メソッドによって割り当てられた推定合計メモリです(複数のスレッドにまたがっていないことを考慮して)。

com.sun.management.ThreadMXBean mxBean = 
      (com.sun.management.ThreadMXBean) ManagementFactory.getThreadMXBean(); 

Javaでオブジェクトの解放というようなイベントがありません。ここで

com.sun.management.ThreadMXBeanのインスタンスを取得する方法です。完全なGCまでオブジェクトが到達可能かどうかを見つけることはできません。 GCでもオブジェクトの「割り当てを解除」しません。通常はライブオブジェクトを処理し、空き領域として扱います。

メソッドを呼び出した後にJavaヒープがどのように変化するかを知る必要がある場合は、コールの前後にヒープスナップショットを作成できます。

+0

お返事ありがとうございます。残念ながら、私のメソッドの実行中に割り当てを監視する必要があるので、これは私のケースではありません。さらに、私はそのメソッド呼び出し専用のスレッドを持つことはできません。考え方は、execute()メソッドのメモリ消費量に応じて、システムで使用されるjava.nio.ByteBufferの数を調整することです。しかし、ヒープスナップショットに関するあなたの考えは、スレッドヒープダンプごとに取ることができる限り面白いかもしれませんが、それは実行可能ではないと私は信じています。 –

関連する問題