C で記述されたアプリケーションの一部があり、JVM を生成し、JNI を使用して Java アプリケーションと対話します。Process Explorer によるメモリ フットプリントが最大 1GB になり、メモリが不足します。私が知る限り、最大2GBまで取得できるはずです。私が信じていることの 1 つは、JVM が使用しているメモリが Process Explorer に表示されないことです。私の xmx は 256 に設定されています。Java 側のメモリを監視するステートメントをいくつか追加しました。これは 256 でピークに達し、GC はその仕事を行っており、その側ではすべて問題ありません。私の質問は、残りの 700 MB 以上はどこで消費されているのでしょうか? Java/JNI/C メモリの専門家はいますか?
6 に答える
JNI コードにリークがある可能性があります。
処理が完了したら、取得したすべてのオブジェクト参照に対して (*jni)->DeleteLocalRef() を使用することを忘れないでください。ネイティブ C バッファを使用して新しい Java オブジェクトを作成する場合は、オブジェクトの作成後にそれらを解放してください。詳細なガイドラインについては、JNI 仕様を確認してください。
使用している VM によっては、JNI チェックをオンにできる場合があります。たとえば、IBM JDK では、「-Xcheck:jni」を指定できます。
JVM を生成しない代わりに、より多くのメモリを割り当てようとする C のテスト アプリを試してください。テスト アプリが 2 GB の壁に到達できるかどうかを確認します。
特に@alexanderのすべての助けに感謝します。Process Explorerでは表示されないすべての余分なメモリがJavaヒープによって使用されていることを発見しました。実際、私が実行した他のテストを介して、JVM のメモリ消費量は、Process Explorer から見たものに含まれています。そのため、ヒープは大量のメモリを消費しています。それについてさらに調査し、別の質問をする必要があります。
C テスト ハーネスを作成し、valgrind/alleyoop を使用して C コードのリークをチェックし、同様に Java jvisualvm ツールを使用します。
JVM ではなく Windows プロセスがメモリ不足であると言う場合、私の最初の推測では、おそらく JVM からいくつかの (独自の) ネイティブ メソッドを呼び出し、それらのネイティブ メソッドがメモリ リークを起こしているのではないでしょうか。したがって、ここで@John Gardnerに同意します。
C および JNI コードは、VM の 256m の外側にあるメモリ (malloc/free/new/etc) も割り当てることができます。xMX は、VM 自体が割り当てるもののみを制限します。Cコードに何を割り当てているか、およびメモリにロードされている他のものに応じて、最大2GBを取得できる場合とできない場合があります。