前言
在之前的文章中我们看到过如下C++代码:
jclass clazz = env->FindClass("***/***/JNIDynamicUtils");
FindClass
就属于jni函数。此文就来稍微讲解下一些常用的jni函数。
C与C++调用函数的区别
如上述代码,则是C++文件内的代码。标准的C实现上述代码的方式是:
jclass clazz = (*env)->FindClass(env, "***/***/JNIDynamicUtils");
看到不同的表示方式便能知道写的是C还是C++了。相比较的话,C++代码还是简洁一些。
JNI函数
以下为部分入门级函数,后续会不断补充。
1. FindClass
jclass FindClass(JNIEnv *env, const char *name);
该函数用于加载本地定义的类。
参数:
env:JNI接口指针。下面将不再介绍 ,在C++代码中,参数不传该值。
name:类全名(即包名后跟类名,之间由“/”分隔)。如果该名称以“[”(数组签名字符)打头,则返回一个数组类。
返回值:
返回类对象全名。如果找不到该类,则返回NULL。
抛出:
ClassFormatError:如果类数据指定的类无效。
ClassCircularityError:如果类或接口是自身的超类或超接口。
NoClassDefFoundError:如果找不到所请求的类或接口的定义。
OutOfMemoryError:如果系统内存不足。
2. GetMethodID
jmethodID GetMethodID(JNIEnv *env, jclass clazz, const char *name, const char *sig);
返回类或接口实例(非静态)方法的方法ID。方法可在某个clazz的超类中定义,也可从clazz继承。该方法由其名称和签名决定。GetMethodID()
可使未初始化的类初始化。要获得构造函数的方法ID,应将<init>
作为方法名,同时将()V
作为返回类型。
参数:
clazz:Java类对象。
name:0终结的UTF-8字符串中的方法名。
sig:0终结的UTF-8字符串中的方法签名。
返回值:
方法ID,如果找不到指定的方法,则为NULL。
抛出:
NoSuchMethodError:如果找不到指定方法。
ExceptionInInitializerError:如果由于异常而导致类初始化程序失败。
OutOfMemoryError:如果系统内存不足。
3. NewObject
jobject NewObject(JNIEnv *env, jclass clazz, jmethodID methodID, ...);
构造新Java对象。方法ID必须通过调用GetMethodID()
获得,为应调用的构造函数方法。clazz参数务必不要引用数组类。
参数:
clazz:Java类对象。
methodID:构造函数的方法ID。
其它参数:传给构造函数的参数。
返回值:
返回Java对象,如果无法构造该对象,则返回NULL。
抛出:
InstantiationException:如果该类为接口或抽象类。
OutOfMemoryError:如果系统内存不足。
其他:构造函数抛出的任何异常。
4. NewStringUTF
jstring NewStringUTF(JNIEnv *env, const char *bytes);
利用UTF-8字符数组构造新java.lang.String对象。
参数:
bytes:指向UTF-8字符串的指针。
返回值:
Java字符串对象。如果无法构造该字符串,则为NULL。
抛出:
OutOfMemoryError:如果系统内存不足。
5. GetStringUTFLength
jsize GetStringUTFLength(JNIEnv *env, jstring string);
以字节为单位返回字符串的UTF-8长度。
参数:
string:Java字符串对象。
返回值:
返回字符串的UTF-8长度。若参数为null,则会异常。
6. Throw
jint Throw(JNIEnv *env, jthrowable obj);
抛出java.lang.Throwable异常对象。
参数:
obj:java.lang.Throwable对象。
返回值:
成功时返回0,失败时返回负数。
抛出:
java.lang.Throwable对象obj。
tip:
与java不同,抛出异常后,后续代码还会继续执行,直至return。
7. ThrowNew
jint ThrowNew(JNIEnv *env, jclass clazz, const char *message);
利用指定类的消息(由message指定)构造异常对象并抛出该异常。
参数:
clazz:java.lang.Throwable的子类。
message:用于构造java.lang.Throwable对象的消息。
返回值:
成功时返回0,失败时返回负数。
抛出:
新构造的java.lang.Throwable对象。
8. GetArrayElements
NativeType *Get<PrimitiveType>ArrayElements (JNIEnv *env, ArrayType array, jboolean*isCopy);
一组返回基本类型数组体的函数。结果在调用相应的ReleaseArrayElements()函数前将一直有效。由于返回的数组可能是Java数组的副本,因此对返回数组的更改不必在基本类型数组中反映出来,直到调用了 ReleaseArrayElements()。如果isCopy不是NULL,*isCopy在复制完成后即被设为JNI_TRUE。如果未复制,则设为JNI_FALSE。
GetArrayElements例程 | 数组类型 | 本地类型 |
---|---|---|
GetBooleanArrayElements() | jbooleanArray | jboolean |
GetByteArrayElements() | jbyteArray | jbyte |
GetCharArrayElements() | jcharArray | jchar |
GetShortArrayElements() | jshortArray | jshort |
GetIntArrayElements() | jintArray | jint |
GetLongArrayElements() | jlongArray | jlong |
GetFloatArrayElements() | jfloatArray | jfloat |
GetDoubleArrayElements() | jdoubleArray | jdouble |
参数:
array:Java字符串对象。
isCopy:指向布尔值的指针。
返回值:
返回指向数组元素的指针,如果操作失败,则为NULL。
9. ReleaseArrayElements
void Release<PrimitiveType>ArrayElements(JNIEnv *env, ArrayType array, NativeType *elems, jint mode);
通知虚拟机平台相关代码无需再访问elems的一组函数。elems参数是一个通过使用对应的GetArrayElements()
函数由array导出的指针。必要时,该函数将把对elems的修改复制回基本类型数组。mode参数将提供有关如何释放数组缓冲区的信息。 如果elems不是array中数组元素的副本,mode将无效。否则,mode将具有下表所述的功能:
基本类型数组释放模 | 动作 |
---|---|
0 | 复制回内容并释放elems缓冲区 |
JNI_COMMIT | 复制回内容但不释放elems缓冲区 |
JNI_ABORT | 释放缓冲区但不复制回变化 |
多数情况下,编程人员将把“0”传给mode参数以确保固定的数组和复制的数组保持一致。其它选项可以使编程人员进一步控制内存 管理,但使用时务必慎重。
参数:
array:Java数组对象。
elems:指向数组元素的指针。
mode:释放模式。
10. NewArray
ArrayType New<PrimitiveType>Array(JNIEnv *env, jsize length);
用于构造新基本类型数组对象的一系列操作。下表说明了特定的基本类型数组构造函数。用户应把NewArray替换为 某个实际的基本类型数组构造函数例程名(见下表),然后将ArrayType替换为该例程相应的数组类型。
NewArray例程 | 数组类型 |
---|---|
NewBooleanArray() | jbooleanArray |
NewByteArray() | jbyteArray |
NewCharArray() | jcharArray |
NewShortArray() | jshortArray |
NewIntArray() | jintArray |
NewLongArray() | jlongArray |
NewFloatArray() | jfloatArray |
NewDoubleArray() | jdoubleArray |
参数:
length:数组长度。
返回值:
Java数组。如果无法构造该数组,则为NULL。
11. SetArrayRegion
void Set<PrimitiveType>ArrayRegion(JNIEnv *env, ArrayType array, jsize start, jsize len, NativeType *buf);
将基本类型数组的某一区域从缓冲区中复制回来的一组函数。下表说明了特定的基本类型数组元素访问器。应进行如下替换:
SetArrayRegion例程 | 数组类型 | 本地类型 |
---|---|---|
SetBooleanArrayRegion() | jbooleanArray | jboolean |
SetByteArrayRegion() | jbyteArray | jbyte |
SetCharArrayRegion() | jcharArray | jchar |
SetShortArrayRegion() | jshortArray | jshort |
SetIntArrayRegion() | jintArray | jint |
SetLongArrayRegion() | jlongArray | jlong |
SetFloatArrayRegion() | jfloatArray | jfloat |
SetDoubleArrayRegion() | jdoubleArray | jdouble |
参数:
array: Java数组。
start:起始下标。
len:要复制的元素数。
buf:源缓冲区。
抛出:
ArrayIndexOutOfBoundsException:如果区域中的某个下标无效。