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访问权限的成员信息