2011.11.21
【Android NDK】JNIEnv*の問題
やはり問題がありました。
現在テストしているプログラムを実行していると
たまに落ちることがありました。
よく調べていくとJNIEnv*の位置が変わっていました。
現在の手順としては、起動時にJNIをたたき、引数で渡されたJNIEnv*をグローバルに
保存して使いまわすという方向でやっていました。
危険だとはわかっていましたがやはりガベコレの関係か場所が変わってしまうっぽいです。
JNIEnv*がないとCからJavaを呼び出すことができないのでどうにかすれば
取得できるだろうと思いいろいろと探してみました。
通常のJNIでは、JNI_GetCreatedJavaVMs関数を使用しJavaVM*を取得し、
これのメソッドのGetEnv関数を使用するとできるらしい。
Link:JNI JavaVMメモ(Hishidama's Java native interface JVM Memo)
試してみたところ、リンク時にエラーになってしまう。
JNI_GetCreatedJavaVMs関数は実装されていないらしい。
感じ的には、JavaVM*が確保できればいいんだろうなと思い
その方向で調べたところこんなものを発見。
Link:NDKでlibdvmを使用してJNI_GetCreatedJavaVMsを利用したいのですが - Android-SDK-Japan | Google グループ
起動時にJNI_OnLoad関数が呼び出されるらしく、ここの引数にJavaVM*が渡される。
これを保存しておけばいいのではないかな?
んで、できたものがこんな感じになりました。
//JavaVM情報 JavaVM *g_JavaVM; /** * JNIロード時に呼び出されるコールバック * @param vm * @aram reserved */ jint JNI_OnLoad( JavaVM* vm, void* reserved ) { //javaVMを保存 g_JavaVM = vm; //__android_log_print( ANDROID_LOG_INFO, "nya", "JNI_OnLoad call..." ); return JNI_VERSION_1_6; } /** * 現在のJNIEnvを取得する * @return 現在のJNIEnv */ JNIEnv *getJNIEnv( void ) { JNIEnv *envRet; jint ret; ret = (*g_JavaVM)->GetEnv( g_JavaVM, (void**)&envRet, JNI_VERSION_1_6 ); if( ret != JNI_OK ) { //取得失敗 return NULL; } return envRet; }
JNIEnv*がほしいときにgetJNIEnv関数を呼び出すと取得することができます。
この処理でJNIEnvの扱いについては解決したぽいのですが、
JavaVMは変更されないのかな?
不安ですけれども前よりはだいぶ安定している感じなので
また問題になりそうであれば変更しましょう。
Android NDKネイティブプログラミング 出村 成和 秀和システム 2011-07 |
関連記事