Android 基于缓存的jobject和methodID从本机函数调用Java函数失败
Java源代码:Android 基于缓存的jobject和methodID从本机函数调用Java函数失败,android,android-ndk,java-native-interface,Android,Android Ndk,Java Native Interface,Java源代码: public void onEventListener(final int eventID, final int arg1, final long arg2, final String message) { Log.d("TEST", "onEventListener() is called - eventID = "+eventID); } JavaVM* gJvm = NULL; pid_t _vm_tid = -1; JNIEnv
public void onEventListener(final int eventID, final int arg1,
final long arg2, final String message)
{
Log.d("TEST", "onEventListener() is called - eventID = "+eventID);
}
JavaVM* gJvm = NULL;
pid_t _vm_tid = -1;
JNIEnv * jEnv = NULL;
jclass native_cls_id = NULL;
jmethodID _onEventListenerID=NULL;
jobject m_nativeObj = NULL;
jint JNI_OnLoad(JavaVM* vm, void* reserved)
{
....
gJvm = vm;
_vm_tid = gettid();
....
}
JNI代码:
public void onEventListener(final int eventID, final int arg1,
final long arg2, final String message)
{
Log.d("TEST", "onEventListener() is called - eventID = "+eventID);
}
JavaVM* gJvm = NULL;
pid_t _vm_tid = -1;
JNIEnv * jEnv = NULL;
jclass native_cls_id = NULL;
jmethodID _onEventListenerID=NULL;
jobject m_nativeObj = NULL;
jint JNI_OnLoad(JavaVM* vm, void* reserved)
{
....
gJvm = vm;
_vm_tid = gettid();
....
}
//作用
void NotifyFromNative(int eventID, int arg1, long arg2, char* message) {
LOGD("Receive_Message_Callback is called - eventID = %d",eventID);
JNIEnv* env = NULL;
pid_t tid = gettid();
LOGD("Step 0");
if (tid != _vm_tid) {
jint ret = gJvm->AttachCurrentThread(&env, NULL);
LOGD("Step 1 - tid != _vm_tid ret=%d",ret);
} else {
LOGD("Step 1 - tid == _vm_tid");
gJvm->GetEnv((void**) &env, JNI_VERSION_1_4);
}
LOGD("Step 2");
jstring jstr = env->NewStringUTF(message);
LOGD("Step 3");
env->CallVoidMethod(m_nativeObj, _onEventListenerID, eventID, arg1, arg2,
jstr);
LOGD("Step 4");
env->DeleteLocalRef(jstr);
if (tid != _vm_tid)
gJvm->DetachCurrentThread();
}
//初始化JNI函数
JNIEXPORT jint JNICALL Java_NativeManager_initialize(JNIEnv * env,
jobject obj) {
LOG_UI("Native initialize is called");
m_nativeObj = env->NewGlobalRef(obj);
jclass cls = env->FindClass(classPathName);
if (cls == NULL) {
LOGE("Can't find class %s", classPathName);
return 0;
}
native_cls_id = (jclass) env->NewGlobalRef(cls);
_onEventListenerID = env->GetMethodID(native_cls_id, "onEventListener",
"(IIJLjava/lang/String;)V");
if (!_onEventListenerID)
{
LOGE("Can't find onEventListener Java method");
return 0;
}
char* message = "test";
jstring jstr = env->NewStringUTF(message);
env->CallVoidMethod(m_nativeObj, _onEventListenerID, 1, 1, 1,
jstr); //This call work well
NotifyFromNative(0, 1, 1, "test"); //<= problem here
}
问题:
public void onEventListener(final int eventID, final int arg1,
final long arg2, final String message)
{
Log.d("TEST", "onEventListener() is called - eventID = "+eventID);
}
JavaVM* gJvm = NULL;
pid_t _vm_tid = -1;
JNIEnv * jEnv = NULL;
jclass native_cls_id = NULL;
jmethodID _onEventListenerID=NULL;
jobject m_nativeObj = NULL;
jint JNI_OnLoad(JavaVM* vm, void* reserved)
{
....
gJvm = vm;
_vm_tid = gettid();
....
}
有人能为我解释一下,尽管创建了对象的全局引用,为什么调用NotifyFromNative(0,1,1,“test”)会出现问题。非常感谢我发现Android JNI函数不能使用长参数。因此,我将长值分解为2个整数值,代码现在正在运行。这是我随机发现的一个非常古老的问题。但目前的答案是错误的。问题就在这里
void NotifyFromNative(int eventID, int arg1, long arg2, char* message) {
应该是
void NotifyFromNative(int eventID, int arg1, jlong arg2, char* message) {
请注意jlong。java中的long是64位。c/c++中的long不能保证达到这个大小。jlong确保了java中long的兼容类型