[TOC]
Java静态和非静态调用native区别
直接先上结论
java申明native方法时,native方法修饰分为static和非static
两个区别在于,对于jobject *obj
:
静态的其实是个Class的对象,类型是java端对应的类,super类型是java/lang/Class
非静态是java端类对象实例,super类型是对应的class对象
如下:
//静态调用
[class xxx.JniCam, class java.lang.Class]
//实例调用
[xxx.JniCam@346a4f, class xxx.JniCam]
测试
- native端实现
static void GeneralCallback(JNIEnv *env, jint type, jobject *objects, int size) {
jclass lds = static_cast<jclass>(gObject);
jclass base = env->FindClass("java/lang/Object");
jobjectArray array = env->NewObjectArray(size, base, base);
for (int i = 0; i < size; i++) {
env->SetObjectArrayElement(array, i, objects[i]);
}
{
pthread_mutex_lock(&gMutex);
jmethodID jniCallback = env->GetStaticMethodID(lds, "JniCallback",
"(I[Ljava/lang/Object;)V");
if (jniCallback != nullptr)
env->CallStaticVoidMethod(lds, jniCallback, type, array);
pthread_mutex_unlock(&gMutex);
}
}
void test(JNIEnv *env, jobject obj, int type) {
jobject objects[2];
objects[0] = obj;
objects[1] = env->GetObjectClass(obj);
GeneralCallback(env, type, objects, 2);
}
JNIEXPORT void JNICALL
Java_xxx_JniCam_init(JNIEnv *env, jobject obj) {
gObject = env->NewGlobalRef(obj);
}
JNIEXPORT void JNICALL Java_xxx_JniCam_test(JNIEnv *env, jobject instance){
test(env, instance, 100);
}
JNIEXPORT void JNICALL Java_xxx_JniCam_testStatic(JNIEnv *env, jobject instance){
test(env, instance, 101);
}
- java端申明
public static native void init();
public static native void testStatic();
public native void test();
public static void JniCallback(int type, Object... info){
Logger.INSTANCE().i("JniCallback", type, info);
}
- java端调用
JniCam.init();
JniCam.testStatic();
new JniCam().test();
- 回调结果
JniCallback 101 [class xxx.JniCam, class java.lang.Class]
JniCallback 100 [xxx.JniCam@346a4f, class xxx.JniCam]
结语
- 总结
以上代码是为了结构清晰,只展示了关键的测试代码,具体结构构建,网上随便搜一个初始教程"hello_world"就可以了,涉及到知识为:
- Jni静态和动态注册,本例使用静态注册的方式
- Jni引用,引用分为局部、全局和弱全局引用
- Jni静态和非静态回调,本例回调的是java端的静态方法,其实了解Java反射的话,对这块会很好理解
- 方法签名类型定义,方法有重载,所以需要签名(也就是参数、返回值)区别一下,这边关于签名的类型定义,了解Smali方面的知识的话,会很容易理解
- 注意
在上面初始化时, 创建了一个全局引用 gObject, 记得是需要在最后(例如:JNI_OnUnload())释放