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  | 








関連記事