JNI 常用技巧
Android 中使用 JNI 的一些常用技巧。
1. JNI中的类型对应关系
C/C++类型 | Java类型 | 具体描述 | 类型署名 |
---|---|---|---|
unsigned char | jboolean | unsigned 8 bits | Z |
signed char | jbyte | signed 8 bits | B |
unsigned short | jchar | unsigned 16 bits | C |
short | jshort | signed 16 bits | S |
long | jint | signed 32 bits | I |
long long __int64 | jlong | signed 64 bits | J |
float | jfloat | 32 bits | F |
double | jdouble | 64 bits | D |
void | V | ||
int[] | jint [] | array | [I |
此外,Java 中的类的类型署名使用的是"L fully-qualified-class ;"形式,例如: Java 中的 java.lang.String ,使用的是"Ljava/lang/String;"名称。
2. C/C++ 中获得 JNIEnv 指针
- 和 Java 虚拟机在同一线程时,可使用 GetEnv 直接获得 JNIEnv 指针:
JavaVM* vm; // ...
JNIEnv* env = NULL;
if (vm->GetEnv((void**)&env, JNI_VERSION_1_6) == JNI_OK) {
// Do something
}
- 和 Java 虚拟机不在同一线程时,要使用 AttachCurrentThread 来获得 JNIEnv 指针,然后在使用完后用 DetachCurrentThread 释放:
JavaVM* vm; // ...
if (vm->AttachCurrentThread(&env, NULL) == JNI_OK) {
// Do something
vm->DetachCurrentThread();
}
3. C/C++ 中构造 Java 对象
在 C/C++ 中构造 Java 对象需要这么几个步骤:
通过 FindClass 找到要构造的 Class
通过 GetMethodID 在已经找到的 Class 中找到对应的构造函数
通过 NewObject 来创建对象
最后在不需要时利用 DeleteLocalRef 来销毁对象
具体的代码如下:
JNIEnv* env; // ...
jclass jclz= env->FindClass("com/example/MyClass");
jmethodID jmid = env->GetMethodID(jclz, "<init>", "()V");
if (jclz && jmid) {
jobject obj = env->NewObject(jclz, jmid);
if (obj != NULL) {
// Do something
env->DeleteLocalRef(obj);
}
}
4. C/C++ 中构造 Java 数组
在 C/C++ 中构造 Java 数组需要这么几个步骤:
通过 NewObjectArray 创建 Java 数组对象
通过 SetObjectArrayElement 来填充数组对象
具体的代码如下:
JNIEnv* env; // ...
int count; // 数组元素数量
jclass jclz; // 数组中的对象
jmethodID jmid; // 数组中对象的构造函数
jobjectArray array = env->NewObjectArray(count, jclz, NULL);
if (array) {
for (int i = 0; i < count; i++) {
// 数组元素的对象
jobject obj = env->NewObject(jclz, jmid);
// Do something
env->SetObjectArrayElement(array, i, obj);
env->DeleteLocalRef(obj);
}
env->DeleteLocalRef(array);
}