jni 类型
简单类型 primitive type
jni有8大基本类型, jboolean,jbyte,jchar,jshort,jint,jfloat,jlong,,jdouble
8位,16位,32位,64位,各两个(在win32平台中,其他平台不一定)
java类型与c++数据类型的映射关系是如下:
jboolean <--> unsigned char
jchar <--> unsigned short
jshort <--> short
jfloat <--> float
jdouble <--> double
这是在 jni.h里定义的,为啥缺了jbyte,jint,jlong的映射呢?
答案是:sun在实现java虚拟机时,考虑到虚拟机可能运行在不同的操作系统和不同的硬件平台上,比如,硬件平台有8位,16位,32位,64位的区别,为了更好地与硬件平台匹配,发挥最好的性能,将一些类型抽取出来,允许在不同的平台上有不同的表示(位数),我们姑且称之为硬件相关类型,jbyte,jint,jlong就属于硬件相关类型。
举列来说,如果你在32位机上,jint表示的是32bit的,而在64位机上,一般是64位即8个字节表示,也就是说,jbyte,jint,jlong在sun的虚拟机上,位数是不定的。
那位数不一定,怎么编译? sun的方法是增加一个机器相关的jni_md.h文件,这里的md是machine dependent(机器相关)的意思。在win32平台中,这三个类型的定义如下:
typedef long jint;
typedef __int64 jlong;
typedef signed char jbyte;
由此可见,在win32平台中,jint是32位的,jlong是64位,jbyte是8位的.
指针类型 reference type
reference 准确的译法,应该是引用,但引用实际上就是指针的一种伪装,只不过更接近人的思维罢了。如果说,"爸爸的爸爸"是一种指针概念,那"爷爷"就是一种引用概念。
jni把类型分为两大类,一个是简单类型,一个是引用类型,下面是引用类型
从上图似乎可以看出,所有引用类型,都从jobject 继承,jarray又被几个简单类型的数组继承.
但实际上这个对象层次,是一种假象,跟我们c++与java中看到的对象层次是有区别的,jobject与LPSTR(字符串指针),本质上没有区别:
1. jobject, jclass,jstring,...等,所有对象,是指针,不是对象本身,而指针是不存在继承关系的,“小狗”的指针,从“动物”的指针继承,这种说法不成立。
2. jobject,jclass,jstring 是一种指针,不存在任何操作方法,好比你不能 LPCSTR->strlen(),在jni中,也没有提供任何 jobject->something() 这种调用。
3. 对这些对象的操作必须依赖于 env对象的操作方法.
看一下,jni.h中对 这些引用对象的定义
class _jobject {};
class _jclass : public _jobject {};
class _jstring : public _jobject {};
...
typedef _jobject *jobject; //_jobject才是类定义,jobject 是否_jobject的指针
typedef _jclass *jclass;
typedef _jstring *jstring;
...
在这些下划线对象中,有什么成员变量,成员函数呢? 答案是你什么也不能得到,比如,你想知道,_jstring对象的字符串长度,你不能 _jstring.length(),得到,而必须env->GetStringLength(jstring) 来得到.
只给你一个对象的指针,不告诉你里面有什么,这样做的好处是实现与接口分离。
jvalue 这个类型,是一个union ,感觉很想com里的variant对象,不过没有指明类型的field
typedef union jvalue {
jboolean z;
jbyte b;
jchar c;
jshort s;
jint i;
jlong j;
jfloat f;
jdouble d;
jobject l;
} jvalue;
我现在还不知道,这个数据类型,什么时候用.
jfieldID是一个java类成员变量的id,这个id在c++中,实际是一个指向结构的一个指针, jmethodID 是成员方法的id, 不管是成员变量还是方法的id,在java类被加载进虚拟机后,是保持不变的。所以从考虑性能计,可以使用静态缓存的方法,先取出来,后面会讲到
字符串类型
这里说的字符串类型,是jni中char * 的格式,不是指 jstring/_jstring,jni也使用 char * 字符串指针,
好下所示:
jmethodID GetMethodID (JNIEnv *env, jclass clazz, const char *name, const char *sig);
但需要注意的是,这里的name,必须是UTF-8的编码,utf-8对于ascii字符,只占一个字节,最多不超过3个字节