Cプログラム内でJVMを起動するJNI呼び出しAPIを使用しています。この状況では、JVMを明示的に破棄するまで有効なJNIEnvポインターを取得します。ローカル/グローバルの区別はここでも適用されますか?JNIEnvは常にスコープ内にあるため、新しく作成されたオブジェクトへのローカル参照の意味は何ですか?
3 に答える
JNIの本はこの状況について少し簡潔ですが、十分に長く研究すれば理解できます。基本的に、ネイティブCスレッドをJVMに接続すると、いくつかのローカル参照を格納できるローカルコンテキストが作成されます。
これらのローカル参照は、DeleteLocalRefを使用して手動で解放するか、DetachThreadを呼び出してローカルコンテキストを破棄するまで、解放されません。JVMへのアタッチとデタッチをあまり行っていない可能性があるため、作成するすべてのローカル参照でDeleteLocalRefを呼び出すことが非常に重要です。
次の自然な質問は、「JVMがデタッチされるまでローカル参照がGCされないのに、なぜグローバル参照を作成するのか」です。ええと、ローカル参照はスレッド間で共有できません。したがって、それを行うには、グローバル参照を作成する必要があります。
JVMを作成したスレッドはJavaスレッドになると思います。これは、Javaで作成されたスレッド、またはAttachCurrentThread()を介して接続されたスレッドと同様に、ローカルスタックフレームを持っています。したがって、作成したオブジェクトはすべて、このスタックフレーム内のローカル参照になり、JVMを破棄するか(メインスレッドをデタッチすることはできません)、またはDeleteLocalRef()を呼び出すと期限切れになります。
おそらく、DettachCurrentThread()を呼び出すと、参照も解放されます。残念ながら、JNI仕様では、呼び出しAPIの参照の動作が明確に定義されておらず、実際のセマンティクスは特定のJVM実装に依存している可能性があります:S