JNI 对象在函数调用中的生命周期

来源:互联网 发布:Ext js proxy api 编辑:程序博客网 时间:2024/04/27 15:20
Java 本地编程接口(Java Native Interface,JNI) 易懂且容易上手,但对于一些新手甚至于一些中级开发者,在编程中都没有把 JNI 对象的生命周期考虑在内。以至于经常碰见莫名的 Crash,或者 segmentation fault。在花费了相当精力去调试后,才发现是 JNI 对象使用不当,当初保存的 JNI 对象已经被系统回收,却仍试图去使用之。本文结合实际开发中遇到的此类问题,讲述和强调了 JNI 对象生命周期的概念,并提出正确的解决方法,希望能和读者分享自己的经验和教训。

问题

在 JNI 编程中常需要从一个普通的 C/C++ 函数中调用 JNI 方法,比如:

long  ProcessKeyboardEventInJava(int keyboardEvent){    long    error = 0;    JNIEnv*    env = g_env;    jclass    that = g_class;    jmethodID    mid = g_mid;    ……    error  = env->CallStaticIntMethod(that, mid, keyboardEvent);    return error;}

ProcessKeyboardEventInJava 只是个普通的 C 函数,目的是把参数中的键盘事件交给 Java 代码处理。它并没有 JNI 参数,却需要调用一个 JNI 方法。那么调用所必需的参数 JNIEnvjclassjmethodID,是如何获得呢?从上面的代码中可以看出,它们来自保存的全局变量 g_envg_classg_mid。这样做对么?安全么?也许这段代码在某种情况下,实现了软件的需求,成功地执行了 Java 的函数,处理了这个键盘事件。在这种情况下,设计者很清楚,也深信 ProcessKeyboardEventInJava 只会在某个 Native 函数返回前被调用。对应的场景代码应该是这样的:

 

本文转自:IBM developerWorks 中国

请点击此处查看全文