JNI学习笔记2——本地代码访问Java代码

    技术2025-09-07  75

    http://blog.csdn.net/jiben071/archive/2010/11/25/6033717.aspx

    (一)本地代码访问Java代码 1.在被调用的C/C++函数中也可以反过来访问java程序中的类 2.javah工具生成的C/C++函数声明中,可以看到两个参数: JNIEXPORT void JNICALL Java_cn_itcast_sayHello(JNIEnv*

    env,jobject obj){ ··· } (二)JNIEnv类型 (1)其实际代表Java环境。通过这个JNIEnv*指针,就可以对Java端

    的代码进行操作。例如,创建Java类的对象,调用Java对象的方法,

    获取Java对象的属性等等。JNIEnv的指针会被JNI传入到本地方法的

    实现函数中来对Java端的代码进行操作。

    (2)JNIEnv类中常用函数: NewObject //创建一个java对象 NewString  //创建一个java的String对象 New<TYPE>Array //创建某一个类型的java数组 Get/Set<TYPE>Field  //获取或设置某一个对象的属性(需接收参数 ) GetStatic/SetStatic<TYPE>Field //获取或设置某一个类的静态属性 (需接收表示类的参数) Call<TYPE>Method  //调用某一类的方法 CallStatic<TYPE>Method  //调用某一个类的静态方法

     

    (三)Java的数据类型在C/C++中的映射关系 Java类型                        本地类型                           JNI定义的别名 int                                  long                                    jint/jsize long                               _int64                                 jlong byte                               signed char                        jbyte boolean                         unsigned char                   jboolean char                               unsigned short                  jchar short                              short                                  jshort float                               float                                   jfloat double                           double                               jdouble object                            _jobject*                            jobject

    (四)jclass的取得 1.为了能够在C/C++中使用java类,JNI.h头文件中专门定义了jclass

    类型来表是Java中的class类 2.JNIEnv类中取得jclass的函数: (1)jclass FindClass(const char* clsName); FindClass会在classpath系统环境变量下寻找类。传入完整类名,注

    意包与包之间是用'/'而不是'.'来分隔 如:jclass cls_string=env->FindClass("java/lang/String"); (2)jclass GetObjectClass(jobject obj); (3)jclass GetSuperClass(jclass obj);

     

    (五)访问java类中的属性与方法 1.JNI在Jni.h头文件中定义了jfieldID,jmethodID类型来分别代表Java

    端的属性和方法。 2.在访问或设置java属性时,需先在本地代码取得代表Java属性的

    jfieldID;同理java方法亦然 3.获取ID方法(JNIEnv): (1)GetFieldID/GetMethodID GetMethodID也能取得构造函数的jmethodID.创建一个java对象时

    可以调用指定的构造方法 如:env->GetMethodID(data_Clazz,"<init>","()V"); (2)GetStaticFieldID/GetStaticMethodID 类似java的Reflect,需要指定类跟属性/方法名来取得相应的jfieldID

    跟jmethodID (3)sign是什么 例如TestNative类中有两个重载方法: package cn.itcast; public class TestNative{     public void function(int i){         System.out.println("Integer:"+i);     }     public void function(double d){         System.out.println("Double:"+d);     } }

    然后在C/C++代码中需要调用其中一个function方法的话··· //首先取得要调用的方法所在的类··· jclass clazz_TestNative=env->FindClass("cn/itcast/TestNative"); //取得jmethodID之后才能进行调用··· jmethodID id_func=env->GetMethodID

    (clazz_TestNative,"function","??"); ······

    但是到底取得是 void function(int i)还是 void function(double d)的jmethodID呢?

    这就是sign的作用了,它用于指定要取得的属性/方法的类型 这里的sign 如果指定为"(I)V"则取回void function(int) 的jmethodID 如果指定为"(D)V"则取回void function(double)的jmethodID

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

     

     

    (五)使用签名取得属性/方法ID的例子 import java.util.Date; public class Hello{     public int property;     public int function(int foo,Date date,int[] arr){         System.out.println("function");         return 0;    }    public native void test(); }

     

     

    //test本地方法的实现: JNIEXPORT void Java_Hello_test(JNIEnv* env,jobject obj){     //因为test不是静态函数,所以传进来的就是调用这个函数的对象     //否则就传入一个jclass对象表示native()方法所在的类     jclass hello_clazz=env->GetObjectClass(obj);     jfieldID filedID_prop=env->GetFieldID

    (hello_calzz,"property","I");     jmethodID methodID_func=env->GetMethodID

    (hello_clazz,"function","(I Ljava/util/Date; [I)I");     env->CallIntMethod(obj,methodID_func,OL,NULL,NULL); }

     

     

    (六)使用javap命令来产生签名 1.javap -s -p [full class Name] -s 表示输出签名信息 -p 同-private,输出包括private访问权限的成员信息

    最新回复(0)