JNI笔记

JNI第一课:

JNI创建过程(连接C++方法)

1、创建调用本地方法的java类
注意:需要定义好native方法
2、用javah命令生成包含native方法的C++头文件

3、引入头文件到C++工程,根据生成的C++头文件来编写C++源文件
注意:头文件中的生成的方法即在java文件中定义的本地方法

4、然后编译,生成动态链接库

5、将生成的dll链接库设置到环境变量下

6、在java中加载动态链接库,然后按和java一样的方式实现
注意:若用ide需重启,因为需要重新读取环境变量

个人体会:
其实jni的调用的方式和普通的java方法调用的方式一样,只是在java文件中定义的方法转到
C++中去实现,就像接口的实现一样,因此首先要建立好接口,然后用其它的类去实现它,与
接口不同之处在于最后实现的地方在定义接口的这个java类中,而接口的实现在其它类(C++
文件)里面,故需要一步加载的过程。


****************************************************************************************************

JNI第二课

java类被C++文件调用

1、C++文件需要找到java类
API:
jclass GetObjectClass(jobject obj) {
return functions->GetObjectClass(this,obj);
}
jclass FindClass(const char *name) {
return functions->FindClass(this, name);
}
最后返回的是java类的引用,在C++头文件生成的函数中有JNIEnv* env, jobject obj这两个参数
则可以调用该头文件的函数。

2、通过返回的引用,获取类中的属性或者方法的ID编号
API:
jfieldID GetFieldID(jclass clazz, const char *name,
const char *sig) {

return functions->GetFieldID(this,clazz,name,sig);
}
jmethodID GetMethodID(jclass clazz, const char *name,
const char *sig) {

return functions->GetMethodID(this,clazz,name,sig);
}
注意:其中的参数sig(签名),可以用javap得到

3、通过获取的属性的id编号,根据属性的类型获取或者设置相对应的属性
API:
例如,获取整型属性的值:
jint GetIntField(jobject obj, jfieldID fieldID) {
return functions->GetIntField(this,obj,fieldID);
}
设置整型属性的值:
void SetIntField(jobject obj, jfieldID fieldID,
jint val) {
functions->SetIntField(this,obj,fieldID,val);
}
依次,获取其它类型的属性与此类似

4、通过获取的方法的id编号,根据返回值的类型获得方法的引用或者是执行此方法
API:
jint CallIntMethod(jobject obj, jmethodID methodID, ...) {

va_list args;
jint result;
va_start(args,methodID);

result = functions->CallIntMethodV(this,obj,methodID,args);
va_end(args);
return result;
}

jint CallIntMethodV(jobject obj, jmethodID methodID,
va_list args) {

re

turn functions->CallIntMethodV(this,obj,methodID,args);
}

jint CallIntMethodA(jobject obj, jmethodID methodID,
const jvalue * args) {

return functions->CallIntMethodA(this,obj,methodID,args);
}
若要调用父类中被覆盖的方法时,用CallNonvirtual(type)Method(the same args),因为在C++中父类方法声
明为virtual类型时,会调用子类方法。


总结
(1)头文件中生成的方法的两个参数是什么?
答:JNIEnv类型实际上代表了java类的环境,它的指针会被JNI传入,因此可以通过该指针操作java
类中的代码。第二个参数即传递的实例对象,如果本地方法不是静态方法则需要传入该方法的
类的实例正如类里面函数默认传入的this,而此处则传入的jobject。
(2)本地get方法获得的属性值是副本,因此在本地方法中对属性值的操作不会改变java类里面的属性
若要改变属性值,则需要用set方法。

********************************************************************************************************************

JNI第三课

java对象的创建:

1、如上找到要实例化的java类FindClass(...)

2、获取初始化方法的jmethodID
API:jmethodID GetMethodID(jclass clazz, const char *name,
const char *sig) {

return functions->GetMethodID(this,clazz,name,sig);
}

其中的name是方法的名称,初始化的name为""

3、创建新对象
API:jobject NewObject(jclass clazz, jmethodID methodID, ...) {

va_list args;
jobject result;
va_start(args, methodID);

result = functions->NewObjectV(this,clazz,methodID,args);

va_end(args);
return result;
}

总结:
(1)在创建新对象后就意味着要用对象里面的方法,故需要访问(call)java中的方法
访问过程如上

***************************************************************************************************

JNI第四课

字符串操作

1、创建与销毁字符串
API:jstring NewString(const jchar *unicode, jsize len) {
return functions->NewString(this,unicode,len);
}
jstring NewStringUTF(const char *utf) {
return functions->NewStringUTF(this,utf);
}
void ReleaseStringChars(jstring str, const jchar *chars) {
functions->ReleaseStringChars(this,str,chars);
}
void ReleaseStringUTFChars(jstring str, const char* chars) {

functions->ReleaseStringUTFChars(this,str,chars);
}
在不使用获得的字符串时都要释放内存

2、将java字符串(UTF-16)转换为C++的字符串(宽字符串或UTF-8)
API: const jchar *GetStringChars(jstring str, jboolean *isCopy) {

return functions->GetStringChars(this,str,isCopy);
}
const char* GetStringUTFChars(jstring str, jboolean *isCopy) {


return functions->GetStringUTFChars(this,str,isCopy);
}
二者区别:分别是去的UTF-16的宽字符串和UTF-8的字符串

数组的处理

1、在获得java类中的数组这个属性后,获取本地数组元素
API:jint * GetArrayElements(jArray array, jboolean *isCopy) {

return functions->GetArrayElements(this,array,isCopy);
}
2、获得数组的长度
API:jsize GetArrayLength(jarray array) {
return functions->GetArrayLength(this,array);
}

3、通过数组的长度,操作数组(注意是长度是jint类型,故操作也应该是根据jint来操作)

总结:
(1)注意内存的释放,在C++里面的执行与java不同,故需要释放内存
内存释放的时间:在不用的时候立即释放
(2)JNI里面的数据类型需要注意(即java的数据类型与C++数据类型的对应情况)























相关主题
相关文档
最新文档