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

(一)本地代码访问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
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值