背景
最近有项目需求,需要在jni中创建多个子线程,并在子线程中,回调java将byte[]数据上报给java处理
demo实例
关键代码
static jmethodID method_callback;
jclass global_class = NULL;
jclass myClass = NULL;
JavaVM* gJavaVM = NULL;
jint JNI_OnLoad(JavaVM *jvm, void* reserved) {
JNIEnv *env;
int status;
jclass clazz;
//全局变量报错jvm
gJavaVM = jvm;
if (jvm->GetEnv((void **) &env, JNI_VERSION_1_4)) {
//ALOGE("JNI version mismatch error");
return JNI_ERR;
}
clazz = env->FindClass(kClassPathName);
//全局变量,保存class类
global_class = (jclass)env->NewGlobalRef(clazz);
//获取class类callback方法
method_callback = (env)->GetStaticMethodID(clazz,"onFrameUpdate","([BI)V");
if (NULL == clazz) {
_err("Unable to find class com.autochips.avm.AVMCam");
return -1;
}
env->NewGlobalRef(clazz);
status = (env)->RegisterNatives(clazz, sMethods, sizeof(sMethods) / sizeof(sMethods[0]));
if (status < 0) {
return JNI_ERR;
}
return JNI_VERSION_1_4;
}
// 子线程调用java
JNIEnv *env = NULL;
int status;
bool isAttached = false;
status = gJavaVM->GetEnv((void**)&env, JNI_VERSION_1_4);
if (status < 0) {
if (gJavaVM->AttachCurrentThread(&env, NULL))将当前线程注册到虚拟机中
{
return;
}
isAttached = true;
}
//实例化该类
jobject jobject = env->AllocObject(global_class);//分配新 Java 对象而不调用该对象的任何构造函数。返回该对象的引用。
jclass clazz = env->GetObjectClass(jobject);
//调用Java方法
avm_cam->get_buf(ch, &buf);
jbyte* buffer = new jbyte[buf.width * buf.height * 3 /2];
memcpy(buffer,buf.ptr,buf.width * buf.height * 3 /2);
jbyteArray bytes = env->NewByteArray(buf.width * buf.height * 3 /2);
env->SetByteArrayRegion(bytes,0,buf.width * buf.height * 3 /2,buffer);
env->CallStaticVoidMethod(clazz, method_callback,bytes,buf.width * buf.height * 3 /2);
env->DeleteLocalRef(bytes);
if (isAttached) {
gJavaVM->DetachCurrentThread();
}
总结
网上查找了很多有关的文章,测试后都无法实现。最后通过下面关键代码实现。
jobject jobject = env->AllocObject(global_class);//分配新 Java 对象而不调用该对象的任何构造函数。返回该对象的引用。
jclass clazz = env->GetObjectClass(jobject);
这两句是比较关键