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ネイティブプログラミング Android NDKネイティブプログラミング
出村 成和

秀和システム 2011-07
売り上げランキング : 76394

Amazonで詳しく見る by G-Tools

ニャッキ格闘列伝 > プログラム >

前の記事:
次の記事:

関連記事

コメントリスト

コメントなし

コメント



*

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)

こんなタグが使えるみたいよ:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>