JNI使用记录

 

1.     JNIJava与本地C/C++代码相互操作的一种方案。

类型           相应的签名  
boolean        Z  
byte            B  
char            C  
short           S  
int             I  
long            J 
float           F  
double          D  
void            V  
object          L用/分隔包的完整类名:   Ljava/lang/String; 
Array          [签名          [I      [Ljava/lang/Object;  
Method         (参数1类型签名 参数2类型签名···)返回值类型签名  

 

 

Java类型      别名             C++本地类型          字节(bit)  
boolean      jboolean            unsigned char      8, unsigned  
byte         jbyte               signed char       8  
char         jchar               unsigned short     16, unsigned  
short        jshort              short               16  
int          jint                long               32  
long         jlong               __int64         64  
float        jfloat              float           32  
double       jdouble             double              64  
void         void                                   n/a 

  

2.     要使用JNI,需要:

1),在Java源程序中使用native关键字声明一个方法。

         如:public native void callCppFunction();

2),然后在命令行提示符下使用javah这个命令来生成关于JNI的本地头文件。

如:javah test.jni.MainArrayTest

         3),在VC Studio中建立一个DLL工程,拷贝这个头文件到该工程目录下,拷贝

         %JAVA_HOME%"include下面的jni.hjni_md.h到工程目录下,或者加到系统目下,具体需要拷贝的头文件还要具体研究。

4),建一个cpp源文件,实现生成的头文件中声明的函数。

5),具体各种函数及数据类型的使用如下:具体自己研究:

l       简单方法调用,基本数据类型的使用

jclass clazz_TestNative = env->GetObjectClass(obj);

jclass m_class=(jclass)env->NewGlobalRef(clazz_TestNative );
jobject m_object=env->NewGlobalRef(obj);

//int type

jfieldID id_number = env->GetFieldID(clazz_TestNative, "number", "I");

jint number = env->GetIntField(obj, id_number);

env->SetIntField(obj, id_number, 1000L);

 

// Method call

 jmethodID id_max = env->GetMethodID(clazz_TestNative, "max", "(DD)D");

 jdouble maxValue = env->CallDoubleMethod(obj, id_max, 3.14, 3.15);

 

// object use

jfieldID id_person = env->GetFieldID(clazz_TestNative, "person", "Ltest/jni/Father;");

jobject person = env->GetObjectField(obj, id_person);

jclass clazz_Father = env->FindClass("test/jni/Father");

jmethodID id_Father_Function = env->GetMethodID(clazz_Father, "function", "()V");

env->CallVoidMethod(person, id_Father_Function);

env->CallNonvirtualObjectMethod(person,clazz_Father, id_Father_Function);

 

l       对象的使用

 

jclass clazz_date = env->FindClass("java/util/Date");

jmethodID outputDate_ID = env->GetMethodID(clazz_date, "<init>", "()V");

jobject date_obj = env->NewObject(clazz_date, outputDate_ID);

jmethodID mid_date_getTime = env->GetMethodID(clazz_date, "getTime", "()J");

unsigned times = env->CallLongMethod(date_obj, mid_date_getTime);

 

l       字符串的简单实用

 

jfieldID fid_msg = env->GetFieldID(env->GetObjectClass(obj), "message", "Ljava/lang/String;");

jstring j_msg = (jstring)env->GetObjectField(obj, fid_msg);

 

// get char point

const jchar *p_jst = env->GetStringChars(j_msg, NULL);

 

jint len = env->GetStringLength(j_msg);

jchar *j_buf = new jchar[len+1];

j_buf[len] = L'"0';

env->GetStringRegion(j_msg, 0, len, j_buf);      

wstring wstr((const wchar_t *)j_buf);

//env->ReleaseStringChars(j_msg, j_buf);//不能释放字符数组啊

delete []j_buf;

std::reverse(wstr.begin(), wstr.end());

jstring jnewStr = env->NewString((const jchar*)wstr.c_str(), wstr.size());

env->SetObjectField(obj, fid_msg, jnewStr);

                  

l       数组的使用

jfieldID fid_arrays = env->GetFieldID(env->GetObjectClass(obj), "arrays", "[I");

jintArray jint_arr = (jintArray)env->GetObjectField(obj, fid_arrays);

jint *int_arr = env->GetIntArrayElements(jint_arr, NULL);

jsize len = env->GetArrayLength(jint_arr);

for(int i = 0; i < len; ++i)

{

// printf  value

}

sort(int_arr, int_arr + len, less_second);

 

env->ReleaseIntArrayElements(jint_arr, int_arr, /*JNI_ABORT/JNI_COMMIT/0*/  0);//

}

bool less_second(const int & m1, const int & m2)

{

        return m1 > m2;

}

上面要注意在JNI中对Java中数据类型的映射,见头文件的声明。

还有注意Java中关于对象类型的表示方法比如:int I, boolean Z,

Object L<类的完整名称,注意包名以/分隔>;,数组[<数据类型>

如果不知道可以使用javap这个反编译器。

        

         6)、更多资料,将Java手册。

         7)、在Main函数中加载动态库。

如:System.loadLibrary("TestNative4");

 

8)、注意在JNI中对Java对象的引用。不然垃圾回收将会产生问题。注意全局引用,局部引用、弱全局引用的使用。

           局部引用,也就是本地方法中返回引用。应该使用DeleteLocalRef释放该引用。NewLocalRef创建。还用很多方式创建。

           全局引用,需要手动释放,防止垃圾回收器回收。需要使用NewGlobalRef函数创建,释放它需要使用DeleteGlobalRef函数。

           弱全局引用,需要编程人员手动释放,但是它不防止垃圾回收器的回收。

           使用NewWeakGlobalRef创建,使用DeleteWeakGlobalref释放。IsSamObject(jobject obj1, jobject obj2)判断弱全局引用指向的对象是否已被回收。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值