【Tech-Android-Jni】Jni中基本方法(2)
Jni中各种特殊的方法。
1). 加载虚拟机:
函数:jint JNI_CreateJavaVM(JavaVM **pvm, void **penv, void args);
参数说明:JavaVM **pvm JAVA虚拟机指针,第二个参数JNIEnv *env是贯穿整个调用过程的一个参数,因为后面的所有函数都需要这个参数,需注意的是第三个参数,在jdk1.1与1.2版本有些不同,在JDK 1.1中第三个参数总是指向一个结构JDK1_ 1InitArgs,这个结构无法完全在所有版本的虚拟机中进行无缝移植。所以为了保证可移植性,建议使用jdk1.2的方法加载虚拟机。
2). 获取指定对象的类定义:
有两种方法可获得类定义,一是在已知类名的情况使用FindClass来获取;二是通过对象直接得到类定义GetObjectClass.
/*
* Class: com_example_jni_ActNative
* Method: nativeExec
* Signature: (I)I
*/
JNIEXPORT jint JNICALL Java_com_example_jni_ActNative_nativeExec
(JNIEnv *env, jclass thiz, jint refer){
CCounter *co= (CCounter*)refer;
jobject jo =(jobject)co->javaObj;
//获取javaobj的值并存在jo变量中 javaobj存在CounterNative中
jclass joClazz = (jclass)env->GetObjectClass(jo);//jo的是调用这个方法的(java层)的参考 获取CounterNative类
jmethodID mid =env->GetMethodID(joClazz,"getNumb","()I");//透过jo可以调用_CounterNative对象的getNumb()方法
int numb = (int)env->CallIntMethod(jo,mid);//透过方法getNumb 获取numb的值
co->n=numb;//将numb赋值给n;
return (jint)co->execute();//返回计算的结果
}
3). 获取要调用的方法:
获得非静态方法:
jmethodID (JNICALL *GetMethodID)(JNIEnv *env, jclass clazz, const char *name, const char *sig);
获得静态方法:
jmethodID (JNICALL *GetStaticMethodID)(JNIEnv *env, jclass class, const char *name, const char *sig);
参数说明:JNIEnv *env初始化是得到的JNI环境;jclass class前面已获取到的类定义;const char *name方法名;const char *sig方法参数定义
详见上代码段中的jmethodID 获取。
4). 调用JAVA类方法:
函数:CallObjectMethod(JNIEnv *env, jobject obj, jmethodID mid);
函数:CallStaticObjectMethod((JNIEnv *env, jobject obj, jmethodID mid);
详见上代码段中的CallIntMethod的方法。
5). 获得类属性的定义:
jfieldID (JNICALL *GetFieldID) (JNIEnv *env, jclass clazz, const char *name, const char *sig);
静态属性:
jfieldID (JNICALL *GetStaticFieldID) (JNIEnv *env, jclass clazz, const char *name, const char *sig);
详细见 jfieldID fid = (jfieldID)env->GetFieldID(clazz,”v”,”I”);//获取调用者的v字段
/*
* Class: com_example_jni_CounterNative
* Method: nativeSetup
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_example_jni_CounterNative_nativeSetup
(JNIEnv *env, jobject thiz){
CCounter *obj = new CCounter();//诞生一个CCounter对象
jclass clazz = (jclass)env->GetObjectClass(thiz);
jfieldID fid = (jfieldID)env->GetFieldID(clazz,"v","I");//获取调用者的v字段
env->SetIntField(thiz,fid,(jint)obj);//设置v的值 关联到CCounter指针上 将CCounter的指针对象存在V字段上
jobject gThiz = (jobject)env->NewGlobalRef(thiz); //获取调用这个方法的类CounterNative的指针
obj->javaObj=(jint)gThiz; //将这个类CounterNative的指针存在javaobj上
};
6). 数组处理:
要创建数组首先要知道类型及长度,JNI提供了一系列的数组类型及操作的函数如:
NewIntArray、NewLongArray、NewShortArray、NewFloatArray、NewDoubleArray、 NewBooleanArray、NewStringUTF、NewCharArray、NewByteArray、NewString,访问通过 GetBooleanArrayElements、GetIntArrayElements等函数。
7). 异常:
由于调用了Java的方法,会产生异常。这些异常在C/C++中无法通过本身的异常处理机制来捕捉到,但可以通过JNI一些函数来获取Java中抛出的异常信息。
8).多线程调用
我们知道JAVA是非常消耗内存的,我们希望在多线程中能共享一个JVM虚拟机,真正消耗大量系统资源的是JAVA虚拟机jvm而不是虚拟机环境 env,jvm是允许多个线程访问的,但是虚拟机环境只能被创建它本身的线程所访问,而且每个线程必须创建自己的虚拟机环境env。JNI提供了两个函 数:AttachCurrentThread和DetachCurrentThread。便于子线程创建自己的虚拟机环境。
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。