2016-09-01 27 views
0

JNIでCライブラリを使用するJavaアプリケーションがあります。JNI NewDoubleArrayメモリリーク

私はJNIに文字列を送り、jdoubleArrayを返すようにします。

JNIEXPORT jdoubleArray JNICALL Java_com_1funcA (JNIEnv *env, jclass class, jstring text){ 

const char *a = (*env)->GetStringUTFChars(env, text, 0); 
char *b; 
funcB(a, &b); 

c_array c; 
c.data = b; 
c.count = strlen(b); 

d_array d = funcA(c); 

(*env)->ReleaseStringUTFChars(env, text, a); 
jdoubleArray java_buffer = (*env)->NewDoubleArray(env, d.count); 
(*env)->SetDoubleArrayRegion(env, java_buffer, 0, d.count, d.doubleArr); 

free(d.doubleArr); 
free(b); 

return java_buffer;} 

これらの行からはメモリリークがあります。

jdoubleArray java_buffer = (*env)->NewDoubleArray(env, d.count); 

java_bufferがjavaに返されるので、ここでそれを解放できません。 それはGCが彼を解放しないようです。

私はthisthisをフォローしましたが、メモリリークを防ぐ正しい方法が見つかりません。

グローバル参照に変更しようとしましたが、 もスレッド内でこれを実行しようとしましたが、デタッチしようとしましたが、依然としてsames結果を受け取ります。

+0

メモリリークがあるとはどのように判断しましたか(それは誤検出ではありません)? – Michael

+0

私はwhile(true)でJavaアプリケーションを実行し、メモリ使用量がいっぱいになり、最終的に1時間後にクラッシュしました。 –

答えて

1

これはリークではありません。 NewDoubleArrayはローカル参照を作成します。 https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/functions.html#local_referencesは「ローカル参照はネイティブメソッド呼び出しの期間有効です」と述べています。ネイティブメソッドが返ってくると、ローカル参照が削除されます。 Java側で新しい参照が作成されるため、あまりに早くガベージコレクションが行われることはありません。 Javaがオブジェクトを参照しなくなったら、ガベージコレクションの対象となります。

グローバル参照を作成してもそれを削除しないと、実際にはリークが作成されることに注意してください。

+0

私は言ったように、私はしばらくの間(真の)関数を呼び出すと、メモリ使用量がいっぱいになっています。 –

+1

その後、漏れは他の場所になければなりません。あなたはJava側のリファレンスを保持しているかもしれないし、 'free'を見逃しているかもしれません。クラッシュが発生する場所を正確に確認してください。ネイティブコードで可能な 'OutOfMemoryError'をキャッチするには、それらを使用する前にJNI呼び出しの戻り値をチェックし、' ExceptionOccurred'(そしておそらく 'ExceptionDescribe')を使用してください – user2543253