私のJavaプログラムがどれだけのメモリを消費するかを予測する方法はありますか?私はC++のバックグラウンドから来ており、クラスに「size_in_bytes()」などのメソッドを実装しており、アプリのランタイムメモリフットプリントをかなり正確に予測できました。今、私はJavaの世界にいますが、それはそれほど簡単ではありません...共有される参照、プール、不変オブジェクトがあります...しかし、見る前にメモリフットプリントを予測できるようにしたいと思います。上のプロセスサイズ。
4 に答える
インストルメンテーション API を使用すると、オブジェクトのサイズを検査できます。これを使用するには少し注意が必要です。「premain」メソッドと追加の VM パラメータが必要ですが、Web 上には多くの例があります。「Java Instrumentation size」でこれらを見つけることができます。
デフォルトのメソッドでは浅いサイズしか得られないことに注意してください。また、コンストラクターの外側でのオブジェクトの構築を回避しない限り (これはほとんど不可能です)、ガベージ コレクションを待機している死んだオブジェクトが周囲に存在します。
ただし、一般的に、生成されるオブジェクトの量を適切に制御できる場合は、これらを使用してアプリケーションのメモリ要件を見積もることができます。
プログラムが消費するメモリの量を予測することはできません。ただし、オブジェクトがどれだけかかるかは予測できます。編集すると、私はほとんど完全に間違っていることがわかりました。このドキュメントでは、オブジェクトのメモリ使用量について詳しく説明しています: http://www.javamex.com/tutorials/memory/object_memory_usage.shtml
一般に、特定のオブジェクトが必要とするものをかなり厳密に予測できます。比較的固定されたオーバーヘッドと、オブジェクト内のインスタンス フィールド、および適度な量のパディングがあります。ただし、オブジェクト サイズは少なくとも (ほとんどの JVM で) 16 バイト境界に切り上げられ、一部の JVM はいくつかのオブジェクト サイズをより大きな境界に切り上げます (標準サイズの事前に割り当てられたオブジェクト フレームを使用できるようにするため)。しかし、これはすべて、特定の JVM に対して比較的固定されています。
もちろん、ガベージ コレクションに必要なオーバーヘッドは異なります。ナイーブ ガベージ コレクターは 100% のオーバーヘッド (割り当てられたバイトごとに少なくとも 1 バイトの空きバイト) を必要としますが、特定の種類の「世代別」コレクターはこれをある程度改善できます。ただし、GC に必要なスペースは、ワークロード (ほとんどの JVM) に大きく依存します。
もう 1 つの問題は、比較的低いレベルの割り当て (使用可能な最大ヒープの 10% しか使用していない) で実行している場合、ガベージが蓄積することです。アクティブに参照されていませんが、ガベージのビットがアクティブなオブジェクトに散在しているため、ワーキング セットを占有します。その結果、ワーキング セットは、現在の全体的なガベージ コレクション ヒープ サイズ (およびその他のシステム オーバーヘッド) とほぼ同じになる傾向があります。
もちろん、より高い使用率で実行するようにヒープ サイズを「調整」することはできますが、それによってガベージ コレクションの頻度が増加します (そして、GC の全体的なコストがより少なくなります)。
プロファイラーを使用すると、常にメモリ内にある一定のオブジェクト セットを理解できます。次に、すべてのコード パスを実行してメモリ リークをチェックする必要があります。JProfilerは、手始めとして適しています。