マルチスレッドの注意点

>JNIの使い方

JNI_CreateJavaVMは一度だけ

でenvとjvmが取得できる。そのenvを使い、Javaのライブラリ、クラスやメソッドのポインタを取得する。でJavaを動かすことができるのはその通り。しかしenvを使う処理をスレッドに入れて同時に実行するとエラーが起こる。
また、そうかといってCreateJavaVMをスレッド内でやる(JNI_CreateJavaVMを複数回行う)のはもっと無理だ。
スレッド内でJNIを通してJava実行するには注意点が二つ。

JNI_CreateJavaVMで取得したenvはスレッド内では使わない


スレッド内(そのスレッドでの処理中)で
jvm->AttachCurrentThread((void**)&env,NULL);
とやり、jvmからそのスレッド専用のenvを貰って(アタッチして)使うこと。
アタッチしたので最後、スレッドが終了する直前にデタッチする。
jvm->DetachCurrentThread();
 

スレッド内で使うJavaクラスのIDやメソッドのIDなどはスレッド専用のenvを使って取得するかNewGlobalRefでグローバル変数にする


クラスIDやメソッドIDはスレッドの外で一度だけ取得し、それを使い回せれば効率的に動作すると思える。
しかしそうやろうとすると正しいenvじゃありませんというかスレッドがどうのとエラーが出る。
クラスIDというのはjobjectで、スレッドをまたいだ別のenvでは処理できない(メソッドIDは使える)
なので、スレッド内でenvをアタッチ、そのenvを使ってスレッド専用のクラスIDを取得するのが必要になる。

あるいはよく使うクラスIDなど広域で使いたいものはNewGlobalRefでグローバルにしてしまうのがより良いようだ。その場合DeleteGlobalRefを行う場所など気を使うことが増える。

0 件のコメント:

コメントを投稿