Android JNI和NewGlobalRef

时间:2015-09-21 01:03:44

标签: java android c android-ndk java-native-interface

我正在使用SDL,而且我几乎整理了我遇到的所有问题。

我正在进行jni调用以初始化框架,然后从中创建一个全局引用,因为这是我现在能想到的最佳方式。

我的大多数JNI函数都使用实例变量来读取文件除外。 这就是我设置globalref的方式。

JNIEXPORT void JNICALL SDL_Android_Init(JNIEnv* mEnv, jobject instance)
{
    Android_JNI_SetupThread();
    mInstance = instance;

    jclass clazz = (*mEnv)->GetObjectClass(mEnv, instance);
    mActivityClass = (jclass)((*mEnv)->NewGlobalRef(mEnv, clazz));
.....
}

我只在这段代码中两次使用这个mActivityClass全局引用来读取一些可以随时调用的函数。

主要问题,专门针对Android JNI。如果我坚持使用globalref,因为android控制它的应用程序的生命周期,ref会导致我的应用程序恢复"即使我试图戒烟。

如果我尝试使用类似DeleteLocalRef的内容清除globalref,那么该应用似乎仍然希望恢复而不是退出。有没有办法阻止这种行为?

另一个问题是,是否可以创建一个非静态JNI函数,该函数可以从代码世界的c方面调用,这样我就可以获得一个实例jobject并使用它来获取类实例

例如,通常你在java中编写一个函数:

public native void do_c_work();

在c方面:

void Java_com_test_java_do_c_work(JNIEnv* env, jobject inst)
{
  ...use the instance do your work
} 

如果某些函数在c方面被调用,我想从java获取一个实例来做什么怎么办。

c功能:

public int get_number();

我有点卡在这里,我不想在这一点上实例化一个新的java对象,主要是因为i saw this而且看起来有点矫枉过正。

必须有一种方法可以克服这个障碍,要么能够在不使用静态或创建新活动的情况下从c调用java,那里已经有一个或者释放了globalref,但是并没有这样做。在这一刻,我似乎对我这么好。

2 个答案:

答案 0 :(得分:0)

一些注意事项:

  1. JNI全球参考不会强制您的应用保持开放状态。垃圾收集器知道它们,但控制生命周期的应用程序框架却没有。应用程序框架本身创建了大量全局引用。 (应用程序不是“垃圾收集”。)

  2. 如果您要删除全局参考,请使用DeleteGlobalRef,而不是DeleteLocalRef

  3. 如果要从C调用非静态Java语言方法,请将Object传递给本机代码,并将invoke a method传递给它。如果在本机方法返回VM后将要使用它,请为jobject创建全局引用。 (我觉得我可能不理解这部分问题。)

  4. 另请参阅JNI TipsJNI spec

答案 1 :(得分:-1)

GlobalRef保存到jclass的目的是什么?如果只是这样你可以得到methodIDs,现在就在这段代码中获取它们并存储它们。它们只是整数,而不是对象引用,因此您不必GlobalRef任何东西。