Android で、異なる Java スレッドから同じ JNI ライブラリの関数を呼び出す場合、JNI 関数は同じネイティブ スレッドで呼び出されますか?それとも異なるネイティブ スレッドで呼び出されますか?
答えはすべての Android バージョンで同じですか?
(AsyncTask
同じネイティブ スレッドで初期化して呼び出す必要がある JNI ライブラリを呼び出す場合、これは最良の選択ではないと思います。)
Android で、異なる Java スレッドから同じ JNI ライブラリの関数を呼び出す場合、JNI 関数は同じネイティブ スレッドで呼び出されますか?それとも異なるネイティブ スレッドで呼び出されますか?
答えはすべての Android バージョンで同じですか?
(AsyncTask
同じネイティブ スレッドで初期化して呼び出す必要がある JNI ライブラリを呼び出す場合、これは最良の選択ではないと思います。)
ネイティブコードに関しては、Javaスレッドとネイティブトレッドの区別はなく、すべてスレッドにすぎません。Javaからネイティブメソッドを呼び出してスレッドを変更することはありません。以前のJavaコードと同じスレッドで実行されます。
Java VMはスレッドごとにいくつかの追加情報を保持するため、ネイティブコードで作成されたスレッドを最初にVMに接続する必要があります。
JNI仕様の次のセクションでは、いくつかのヒントを示します。
VMの作成
JNI_CreateJavaVM()関数は、Java VMをロードして初期化し、JNIインターフェース・ポインターへのポインターを返します。JNI_CreateJavaVM()を呼び出したスレッドは、メインスレッドと見なされます。
VMへの接続
JNIインターフェース・ポインター(JNIEnv)は、現在のスレッドでのみ有効です。別のスレッドがJavaVMにアクセスする必要がある場合は、最初にAttachCurrentThread()を呼び出して、自身をVMに接続し、JNIインターフェースポインターを取得する必要があります。VMに接続されると、ネイティブスレッドは、ネイティブメソッド内で実行される通常のJavaスレッドと同じように機能します。ネイティブスレッドは、DetachCurrentThread()を呼び出して自身をデタッチするまで、VMに接続されたままになります。
アタッチされたスレッドには、妥当な量の作業を実行するのに十分なスタックスペースが必要です。スレッドごとのスタックスペースの割り当ては、オペレーティングシステムによって異なります。たとえば、pthreadを使用すると、スタックサイズをpthread_createのpthread_attr_t引数で指定できます。
VMからの切り離し
VMに接続されたネイティブスレッドは、終了する前にDetachCurrentThread()を呼び出して自身をデタッチする必要があります。呼び出しスタックにJavaメソッドがある場合、スレッドはそれ自体をデタッチできません。