を取り付けますJNIは、私はJNIコールバックを持って取り外し/スレッドメモリ管理
void callback(Data *data, char *callbackName){
JNIEnv *env;
jvm->AttachCurrentThread((void **)&env, NULL);
/* start useful code*/
/* end useful code */
jvm->DetachCurrentThread();
}
私はこの(空の便利なコード)のようにそれを実行すると、私はメモリリークを取得します。私が全体の方法をコメントアウトすると、漏れはありません。スレッドの着脱の正しい方法は何ですか?
私のアプリケーションではリアルタイムのサウンドデータが処理されるため、データ処理を担当するスレッドは、別のバッチを処理するためにできるだけ早く実行する必要があります。これらのコールバックのために、私は新しいスレッドを作成します。毎秒数十、数百もの数があり、JVMに接続し、グラフを再ペイントし、切り離して死ぬコールバック関数を呼び出します。これは正しいことでしょうか?漏れたメモリをどのように処理するのですか?
EDIT:タイプミス
私が必要mimimalコード作成しているOK:
package test;
public class Start
{
public static void main(String[] args) throws InterruptedException{
System.loadLibrary("Debug/JNITest");
start();
}
public static native void start();
}
と
#include <jni.h>
#include <Windows.h>
#include "test_Start.h"
JavaVM *jvm;
DWORD WINAPI attach(__in LPVOID lpParameter);
JNIEXPORT void JNICALL Java_test_Start_start(JNIEnv *env, jclass){
env->GetJavaVM(&jvm);
while(true){
CreateThread(NULL, 0, &(attach), NULL, 0, NULL);
Sleep(10);
}
}
DWORD WINAPI attach(__in LPVOID lpParameter){
JNIEnv *env;
jvm->AttachCurrentThread((void **)&env, NULL);
jvm->DetachCurrentThread();
return 0;
}
と私はVisualJMプロファイラを実行したとき、私はいつもの鋸歯状のパターンを取得し、そこには漏れはありません。ヒープ使用量は約5MBでピークに達しました。しかし、プロセスエクスプローラを実際に観察すると、メモリがゆっくりと立ち上がり、立ち上がり、1分ほどで4K秒後に突然この割り当てられたメモリがすべて低下します。これらのドロップは、ガベージコレクションには対応していません(プロファイラーのノコギリよりも少ない頻度で発生し、メモリの割り当てを減らします)。
だから、私の最善の策は、数万のmilisecond-livesスレッドを処理するいくつかのOSの動作です。いくつかの教祖はこれについて説明していますか?ネイティブコードから戻ってのJavaを呼び出す約
私はあなたの意見を見て、私は通常同意するでしょう。私が作成しているスレッドは本当に短命です。私はそれらを(WinApi CreateThreadを使って)作成し、直ちにJVMに添付します。Javaでは、Swingグラフに新しい値を再描画します。それらが完了すると、それらは分離して実行を停止します(0を返します)。その時点で、それらはOSによって破壊されるべきです。それらはJavaに新しい値を渡すために使用されます。各サウンドチャンネルには1秒間に約40個のチャンネルがあります(私は最大32チャンネルを扱います)。 –
スレッドプールを検討するとよいでしょう。新しいスレッドを継続的に生成するのではなく、スレッドを長くしてキューから入力を取得するようにします。これにより、OSとJavaの両方のスレッド管理オーバーヘッドが削減されます。 – technomage
メソッドを呼び出すだけでなく、JNIでJavaのものを実行している場合、それらのアクションについてローカルフレームをプッシュ/ポップすることもできます。 – technomage