访问静态字段
GetStaticFieldID
jfieldID GetStaticFieldID(JNIEnv *env, jclass clazz,
const char *name, const char *sig);
获取类的静态字段ID。该字段由其名称和签名指定。GetStatic<type>Field和SetStatic<type>Field访问器函数系列使用字段ID来检索静态字段。
GetStaticFieldID()会导致未初始化的类被初始化。
链接:
- JNIEnv接口函数表中的索引为144。
参数:
- env:JNI接口指针。
- clazz:Java类对象。
- name:静态字段名称,以0终止的修改后的UTF-8字符串。
- sig:字段签名,以0终止的修改后的UTF-8字符串。
返回值:
- 返回字段ID,如果找不到指定的静态字段,则返回NULL。
抛出:
- NoSuchFieldError:如果找不到指定的静态字段。
- ExceptionInInitializerError:如果类初始化程序由于异常而失败。
- OutOfMemoryError:如果系统内存不足。
GetStatic<type>Field 例程
NativeType GetStatic<type>Field(JNIEnv *env, jclass clazz,
jfieldID fieldID);
该访问器例程系列返回对象的静态字段的值。要访问的字段由字段ID指定,该字段ID通过调用 GetStaticFieldID() 获得。
以下表格描述了获取例程名称和结果类型的系列。您应该将GetStatic<type>Field中的“type”替换为字段的Java类型或来自表格的实际静态字段访问器例程名称之一,并将NativeType替换为该例程的相应本机类型。
GetStatic<type>Field访问器例程系列
GetStatic<type>Field Routine Name | Native Type |
GetStaticObjectField() | jobject |
GetStaticBooleanField() | jboolean |
GetStaticByteField() | jbyte |
GetStaticCharField() | jchar |
GetStaticShortField() | jshort |
GetStaticIntField() | jint |
GetStaticLongField() | jlong |
GetStaticFloatField() | jfloat |
GetStaticDoubleField() | jdouble |
参数:
- env:JNI接口指针。
- clazz:Java类对象。
- fieldID:静态字段ID。
返回值:
- 返回静态字段的内容。
SetStatic<type>Field例程
void SetStatic<type>Field(JNIEnv *env, jclass clazz,
jfieldID fieldID, NativeType value);
该访问器例程系列设置对象的静态字段值。要访问的字段由字段ID指定,该字段ID通过调用GetStaticFieldID()获得。
以下表格描述了设置例程名称和值类型。您应该将SetStatic<type>Field中的“type”替换为字段的Java类型或来自表格的实际设置静态字段例程名称之一,并将NativeType替换为该例程的相应本机类型。
SetStatic<type>Field访问器例程系列
GetStatic<type>Field Routine Name | Native Type |
SetStaticObjectField() | jobject |
SetStaticBooleanField() | jboolean |
SetStaticByteField() | jbyte |
SetStaticCharField() | jchar |
SetStaticShortField() | jshort |
SetStaticIntField() | jint |
SetStaticLongField() | jlong |
SetStaticFloatField() | jfloat |
SetStaticDoubleField() | jdouble |
参数:
- env:JNI接口指针。
- clazz:Java类对象。
- fieldID:静态字段ID。
- value:字段的新值。
调用静态方法
GetStaticMethodID
jmethodID GetStaticMethodID(JNIEnv *env, jclass clazz,
const char *name, const char *sig);
获取类的静态方法ID。该方法由其名称和签名指定。
GetStaticMethodID()会导致未初始化的类被初始化。
链接:
- JNIEnv接口函数表中的索引为113。
参数:
- env:JNI接口指针。
- clazz:Java类对象。
- name:静态方法名称,以0终止的修改后的UTF-8字符串。
- sig:方法签名,以0终止的修改后的UTF-8字符串。
返回值:
- 返回方法ID,如果操作失败,则返回NULL。
抛出:
- NoSuchMethodError:如果找不到指定的静态方法。
- ExceptionInInitializerError:如果类初始化程序由于异常而失败。
- OutOfMemoryError:如果系统内存不足。
CallStatic<type>Method例程、 CallStatic<type>MethodA例程、 CallStatic<type>MethodV例程
NativeType CallStatic<type>Method(JNIEnv *env, jclass clazz,
jmethodID methodID, ...);
NativeType CallStatic<type>MethodA(JNIEnv *env, jclass clazz,
jmethodID methodID, jvalue *args);
NativeType CallStatic<type>MethodV(JNIEnv *env, jclass clazz,
jmethodID methodID, va_list args);
该操作系列根据指定的方法ID在Java对象上调用静态方法。methodID参数必须通过调用GetStaticMethodID() 获得。
方法ID必须从clazz派生,而不是从其超类中派生。
CallStatic<type>Method例程
- 程序员应该将要传递给方法的所有参数立即放在methodID参数后面。CallStatic<type>Method例程接受这些参数并将它们传递给程序员希望调用的Java方法。
CallStatic<type>MethodA例程
- 程序员应该将要传递给方法的所有参数放在一个jvalues数组中,该数组紧随methodID参数。CallStaticMethodA例程接受该数组中的参数,并将它们传递给程序员希望调用的Java方法。
CallStatic<type>MethodV例程
- 程序员应该将要传递给方法的所有参数放在一个va_list类型的args参数中,该参数紧随methodID参数。CallStaticMethodV例程接受这些参数,并将它们传递给程序员希望调用的Java方法。
以下表格根据其结果类型描述了每个方法调用例程。您应该将CallStatic<type>Method中的“type”替换为方法的Java类型或来自表格的实际方法调用例程名称之一,并将NativeType替换为该例程的相应本机类型。
CallStatic<type>Method调用例程
CallStatic<type>Method Routine Name | Native Type |
CallStaticVoidMethod() CallStaticVoidMethodA() CallStaticVoidMethodV() | void |
CallStaticObjectMethod() CallStaticObjectMethodA() CallStaticObjectMethodV() | jobject |
CallStaticBooleanMethod() CallStaticBooleanMethodA() CallStaticBooleanMethodV() | jboolean |
CallStaticByteMethod() CallStaticByteMethodA() CallStaticByteMethodV() | jbyte |
CallStaticCharMethod() CallStaticCharMethodA() CallStaticCharMethodV() | jchar |
CallStaticShortMethod() CallStaticShortMethodA() CallStaticShortMethodV() | jshort |
CallStaticIntMethod() CallStaticIntMethodA() CallStaticIntMethodV() | jint |
CallStaticLongMethod() CallStaticLongMethodA() CallStaticLongMethodV() | jlong |
CallStaticFloatMethod() CallStaticFloatMethodA() CallStaticFloatMethodV() | jfloat |
CallStaticDoubleMethod() CallStaticDoubleMethodA() CallStaticDoubleMethodV() | jdouble |
参数:
- env:JNI接口指针。
- clazz:Java类对象。
- methodID:静态方法ID。
CallStatic<type>Method例程的额外参数:
- 静态方法的参数。
CallStatic<type>MethodA例程的额外参数:
- args:参数数组。
CallStatic<type>MethodV例程的额外参数:
- args:参数的va_list。
返回值:
- 返回调用静态Java方法的结果。
抛出:
- Java方法执行期间引发的异常。
字符串操作
NewString
jstring NewString(JNIEnv *env, const jchar *unicodeChars,
jsize len);
从Unicode字符数组构造一个新的java.lang.String对象。
链接:
- JNIEnv接口函数表中的索引为163。
参数:
- env:JNI接口指针。
- unicodeChars:指向Unicode字符串的指针。
- len:Unicode字符串的长度。
返回值:
- 返回Java字符串对象,如果无法构造字符串,则返回NULL。
抛出:
- OutOfMemoryError:如果系统内存不足。
GetStringLength
jsize GetStringLength(JNIEnv *env, jstring string);
返回Java字符串的长度(Unicode字符数)。
链接:
- JNIEnv接口函数表中的索引为164。
参数:
- env:JNI接口指针。
- string:Java字符串对象。
返回值:
- 返回Java字符串的长度。
GetStringChars
const jchar * GetStringChars(JNIEnv *env, jstring string,
jboolean *isCopy);
返回指向字符串的Unicode字符数组的指针。此指针在调用ReleaseStringChars()之前有效。
如果isCopy不为NULL,则如果进行了复制,则* isCopy设置为JNI_TRUE;如果没有进行复制,则设置为JNI_FALSE。
链接:
- JNIEnv接口函数表中的索引为165。
参数:
- env:JNI接口指针。
- string:Java字符串对象。
- isCopy:指向布尔值的指针。
返回值:
- 返回指向Unicode字符串的指针,如果操作失败,则返回NULL。
ReleaseStringChars
void ReleaseStringChars(JNIEnv *env, jstring string, const jchar *chars);
该函数通知虚拟机,本地代码不再需要访问chars。chars参数是通过使用GetStringChars()从string获得的指针。
链接: JNIEnv接口函数表中的索引166。
参数:
- env:JNI接口指针。
- string:Java字符串对象。
- chars:指向Unicode字符串的指针。
NewStringUTF
jstring NewStringUTF(JNIEnv *env, const char *bytes);
NewStringUTF 函数根据 UTF-8 编码的字符数组构造一个新的 java.lang.String 对象。
链接:
- JNIEnv 接口函数表中的第 167 项。
参数:
- env:JNI 接口指针。
- bytes:指向 UTF-8 编码的字符串的指针。
返回值:
- 返回一个 Java 字符串对象,如果无法构造该字符串,则返回 NULL。
抛出异常:
- OutOfMemoryError:如果系统内存不足。
GetStringUTFLength
jsize GetStringUTFLength(JNIEnv *env, jstring string);
获取字符串的修改后的 UTF-8 编码表示的字节数。
连接:
- JNIEnv 接口函数表中的第 168 个索引。
参数:
- env:JNI 接口指针。
- string:Java 字符串对象。
返回值:
- 返回字符串的 UTF-8 长度。
GetStringUTFChars
const char * GetStringUTFChars(JNIEnv *env, jstring string,
jboolean *isCopy);
函数功能:
- 返回一个指向以修改过的UTF-8编码表示的字符串的字节数组的指针。这个数组在通过ReleaseStringUTFChars()释放之前都是有效的。如果isCopy不是NULL,则*isCopy在进行复制时将被设置为JNI_TRUE;如果没有复制,则将其设置为JNI_FALSE。
LINKAGE:
- JNIEnv接口函数表中的第169个索引。
参数:
- env:JNI接口指针。
- string:一个Java字符串对象。
- isCopy:一个指向布尔值的指针。
返回值:
- 返回一个指向修改过的UTF-8字符串的指针,如果操作失败,则返回NULL。
ReleaseStringUTFChars
void ReleaseStringUTFChars(JNIEnv *env, jstring string,
const char *utf);
功能:
- 通知虚拟机本地代码不再需要访问 utf。utf 参数是从字符串使用 GetStringUTFChars() 获得的指针。
链接:
- JNIEnv 接口函数表中的索引 170。
参数:
- env:JNI 接口指针。
- string:一个 Java 字符串对象。
- utf:指向一个修改过的 UTF-8 字符串的指针。
注:
- 在 JDK/JRE 1.1 中,程序员可以在用户提供的缓冲区中获取基本数组元素。自 JDK/JRE 1.2 开始,提供了额外的一组函数,允许本地代码在用户提供的缓冲区中获取 Unicode(UTF-16)或修改过的 UTF-8 编码的字符。请参阅下面的函数。
GetStringRegion:
void GetStringRegion(JNIEnv *env, jstring str, jsize start, jsize len, jchar *buf);
功能:
- 将从偏移量start开始的len个Unicode字符复制到给定的缓冲区buf中。
- 如果索引溢出,则抛出StringIndexOutOfBoundsException异常。
链接:
- JNIEnv接口函数表中的索引为220。 自JDK/JRE 1.2起可用。
GetStringUTFRegion:
void GetStringUTFRegion(JNIEnv *env, jstring str, jsize start, jsize len, char *buf);
功能:
- 将从偏移量start开始的len个Unicode字符转换为修改后的UTF-8编码,并将结果放置在给定的缓冲区buf中。
- 如果索引溢出,则抛出StringIndexOutOfBoundsException异常。
链接:
- JNIEnv接口函数表中的索引为221。 自JDK/JRE 1.2起可用。
GetStringCritical和ReleaseStringCritical函数:
const jchar * GetStringCritical(JNIEnv *env, jstring string, jboolean *isCopy);
void ReleaseStringCritical(JNIEnv *env, jstring string, const jchar *carray);
功能:
- 这两个函数的语义与现有的Get/ReleaseStringChars函数类似。如果可能,虚拟机将返回一个指向字符串元素的指针;否则,将进行复制。然而,这些函数的使用受到显著限制。在由Get/ReleaseStringCritical调用包围的代码段中,本机代码不能发出任意JNI调用,或导致当前线程阻塞。Get/ReleaseStringCritical的限制与Get/ReleasePrimitiveArrayCritical的限制类似。
链接(GetStringCritical):
- JNIEnv接口函数表中的索引为224。
链接(ReleaseStingCritical):
- JNIEnv接口函数表中的索引为225。
自JDK/JRE 1.2起可用。
数组操作
GetArrayLength
jsize GetArrayLength(JNIEnv *env, jarray array);
功能:
- 返回数组中的元素个数。
链接:
- JNIEnv 接口函数表中的索引为 171。
参数:
- env:JNI 接口指针。
- array:Java 数组对象。
返回值:
- 返回数组的长度。
NewObjectArray
jobjectArray NewObjectArray(JNIEnv *env, jsize length,
jclass elementClass, jobject initialElement);
功能:
- 构造一个新的对象数组,其元素为类 elementClass。所有元素的初始值都设置为 initialElement。
链接:
- JNIEnv 接口函数表中的索引为 172。
参数:
- env:JNI 接口指针。
- length:数组大小。
- elementClass:数组元素类。
- initialElement:初始化值。
返回值:
- 返回 Java 数组对象,如果无法构造数组,则返回 NULL。
异常:
- OutOfMemoryError:如果系统内存不足。
GetObjectArrayElement
jobject GetObjectArrayElement(JNIEnv *env,
jobjectArray array, jsize index);
功能:
- 获取一个对象数组的元素。
连接(LINKAGE):
- JNIEnv接口函数表中的索引173。
参数(PARAMETERS):
- env:JNI接口指针。
- array:一个Java数组。
- index:数组下标。
返回值(RETURNS):
- 返回一个Java对象。
抛出异常(THROWS):
- 如果index没有在数组中指定一个有效的索引,则会抛出ArrayIndexOutOfBoundsException异常。
SetObjectArrayElement
void SetObjectArrayElement(JNIEnv *env, jobjectArray array,
jsize index, jobject value);
功能
- 设置对象数组中的一个元素。
链接:
- JNIEnv接口函数表中的第174项。
参数:
- env:JNI接口指针。
- array:Java数组。
- index:数组下标。
- value:新的值。
抛出:
- ArrayIndexOutOfBoundsException:如果index不是数组中的有效下标。
- ArrayStoreException:如果value的类不是数组元素类的子类。
New<PrimitiveType>Array 系列函数
ArrayType New<PrimitiveType>Array(JNIEnv *env, jsize length);
功能:
- New<PrimitiveType>Array是一组操作,用于构造新的原始数组对象。以下表格描述了特定原始数组构造函数。您应该将New<PrimitiveType>Array替换为来自此表中实际原始数组构造函数例程之一的名称,并将ArrayType替换为该例程的相应数组类型。
New<PrimitiveType>Array原始数组构造函数组
New<PrimitiveType>Array Routines | Array Type |
NewBooleanArray() | jbooleanArray |
NewByteArray() | jbyteArray |
NewCharArray() | jcharArray |
NewShortArray() | jshortArray |
NewIntArray() | jintArray |
NewLongArray() | jlongArray |
NewFloatArray() | jfloatArray |
NewDoubleArray() | jdoubleArray |
参数:
- env:JNI接口指针。
- length:数组长度。
返回值:
- 返回一个Java数组对象,如果无法构造该数组,则返回NULL。
Get<PrimitiveType>ArrayElements 的函数族
NativeType *Get<PrimitiveType>ArrayElements(JNIEnv *env,
ArrayType array, jboolean *isCopy);
功能:
- 这是一个函数族,用于返回原始类型数组的内容。返回结果在调用相应的ReleaseArrayElements()函数之前是有效的。由于返回的数组可能是Java数组的副本,所以对返回的数组所做的更改不一定会反映在原始数组中,直到调用ReleaseArrayElements()函数。
- 如果isCopy不为NULL,则如果复制了数组,则*isCopy设置为JNI_TRUE;如果没有复制,则设置为JNI_FALSE。
下表描述了具体的原始类型数组元素访问器。您应该进行以下替换:
- 用以下表中的实际原始元素访问例程名称之一替换GetArrayElements。
- 用相应的数组类型替换ArrayType。
- 用相应的本地类型替换NativeType。
无论布尔数组在Java虚拟机中如何表示,GetBooleanArrayElements()始终返回指向jbooleans的指针,其中每个字节表示一个元素(展开表示)。所有其他类型的数组都保证在内存中是连续的。
Get<PrimitiveType>ArrayElements 访问系列函数
Get<PrimitiveType>ArrayElements Routines | Array Type | Native Type |
GetBooleanArrayElements() | jbooleanArray | jboolean |
GetByteArrayElements() | jbyteArray | jbyte |
GetCharArrayElements() | jcharArray | jchar |
GetShortArrayElements() | jshortArray | jhort |
GetIntArrayElements() | jintArray | jint |
GetLongArrayElements() | jlongArray | jlong |
GetFloatArrayElements() | jfloatArray | jfloat |
GetDoubleArrayElements() | jdoubleArray | jdouble |
参数:
- env:JNI 接口指针。
- array:Java 字符串对象。
- isCopy:一个指向布尔值的指针,用于指示是否复制了数组元素。
返回值:
- 如果操作成功,返回指向数组元素的指针;否则返回 NULL。
Release<PrimitiveType>ArrayElements例程
void Release<PrimitiveType>ArrayElements(JNIEnv *env,
ArrayType array, NativeType *elems, jint mode);
功能:
- 这是一组函数,用于通知虚拟机本地代码不再需要访问 elems 数组。elems 参数是一个指针,由使用相应的 Get<PrimitiveType>ArrayElements() 函数从数组派生而来。如果必要,此函数会将所有对 elems 所做的更改复制回原始数组。
- mode 参数提供有关如何释放数组缓冲区的信息。如果 elems 不是数组中元素的副本,则 mode 不起作用。否则,mode 具有以下影响,如下表所示:
基本数组释放模式
mode | 操作 |
复制回内容并释放 elems 缓冲区 | |
JNI_COMMIT | 复制回内容但不释放 elems 缓冲区 |
JNI_ABORT | 释放缓冲区而不复制可能的更改 |
在大多数情况下,程序员将“0”传递给 mode 参数,以确保固定和复制数组的行为一致。其他选项为程序员提供了更多关于内存管理的控制,应谨慎使用。
下表描述了组成基本数组释放器系列的特定例程。您应进行以下替换:
- 将 Release<PrimitiveType>ArrayElements 替换为以下表中的实际基本数组释放例程名称之一。
- 将 ArrayType 替换为相应的数组类型。
- 将 NativeType 替换为该例程的相应本机类型。
基本数组释放例程系列 Release<PrimitiveType>ArrayElements
Release<PrimitiveType>ArrayElements例程 | 数组类型 | 本机类型 |
ReleaseBooleanArrayElements() | jbooleanArray | jboolean |
ReleaseByteArrayElements() | jbyteArray | jbyte |
ReleaseCharArrayElements() | jcharArray | jchar |
ReleaseShortArrayElements() | jshortArray | jshort |
ReleaseIntArrayElements() | jintArray | jint |
ReleaseLongArrayElements() | jlongArray | jlong |
ReleaseFloatArrayElements() | jfloatArray | jfloat |
ReleaseDoubleArrayElements() | jdoubleArray | jdouble |
参数:
- env:JNI接口指针。
- array:Java数组对象。
- elems:指向数组元素的指针。
- mode:释放模式。
Get<PrimitiveType>ArrayRegion函数族
void Get<PrimitiveType>ArrayRegion(JNIEnv *env, ArrayType array,
jsize start, jsize len, NativeType *buf);
功能:
- 是一组用于将原生数组的一部分复制到缓冲区的函数。
以下表格描述了具体的原生数组元素访问器。您应该进行以下替换:
- 将Get<PrimitiveType>ArrayRegion替换为以下表格中实际的原始元素访问器例程之一。
- 将ArrayType替换为相应的数组类型。
- 将NativeType替换为该例程的相应本地类型。
Get<PrimitiveType>ArrayRegion函数族的数组访问例程
Get<PrimitiveType>ArrayRegion例程 | 数组类型 | 本地类型 |
GetBooleanArrayRegion() | jbooleanArray | jboolean |
GetByteArrayRegion() | jbyteArray | jbyte |
GetCharArrayRegion() | jcharArray | jchar |
GetShortArrayRegion() | jshortArray | jhort |
GetIntArrayRegion() | jintArray | jint |
GetLongArrayRegion() | jlongArray | jlong |
GetFloatArrayRegion() | jfloatArray | jloat |
GetDoubleArrayRegion() | jdoubleArray | jdouble |
参数:
- env:JNI接口指针。
- array:Java数组。
- start:起始索引。
- len:要复制的元素数量。
- buf:目标缓冲区。
抛出:
- 如果区域中的一个索引无效,则抛出ArrayIndexOutOfBoundsException。
注意:自JDK/JRE 1.1版本以来,程序员可以使用Get/Release<primitivetype>ArrayElements函数获取原始类型数组元素的指针。如果虚拟机支持固定,将返回对原始数据的指针;否则,将进行复制。
从JDK/JRE 1.3版本开始引入了新函数,即使虚拟机不支持固定,本地代码也可以获取数组元素的直接指针。
GetPrimitiveArrayCritical、ReleasePrimitiveArrayCritical
void * GetPrimitiveArrayCritical(JNIEnv *env, jarray array, jboolean *isCopy);
void ReleasePrimitiveArrayCritical(JNIEnv *env, jarray array, void *carray, jint mode);
这两个函数的语义与现有的 Get/Release<primitivetype>ArrayElements 函数非常相似。如果可能,VM 将返回一个指向原始数据的原始指针;否则,将创建一个副本。
然而,这些函数的使用受到重大限制。
在调用 GetPrimitiveArrayCritical 后,本机代码不应长时间运行,直到调用 ReleasePrimitiveArrayCritical。我们必须将这对函数内的代码视为运行在“临界区域”中。在临界区域中,本机代码不能调用其他 JNI 函数或任何可能导致当前线程阻塞并等待另一个 Java 线程的系统调用。 (例如,当前线程不能在由另一个 Java 线程编写的流上调用 read。)
这些限制使得本机代码更有可能获得未复制的数组版本,即使 VM 不支持固定。例如,当本机代码持有通过 GetPrimitiveArrayCritical 获得的数组指针时,VM 可能会暂时禁用垃圾回收。
多对 GetPrimtiveArrayCritical 和 ReleasePrimitiveArrayCritical 可以嵌套。例如:
jint len = (*env)->GetArrayLength(env, arr1);
jbyte *a1 = (*env)->GetPrimitiveArrayCritical(env, arr1, 0);
jbyte *a2 = (*env)->GetPrimitiveArrayCritical(env, arr2, 0);
/* We need to check in case the VM tried to make a copy. */
if (a1 == NULL || a2 == NULL) {
... /* out of memory exception thrown */
}
memcpy(a1, a2, len);
(*env)->ReleasePrimitiveArrayCritical(env, arr2, a2, 0);
(*env)->ReleasePrimitiveArrayCritical(env, arr1, a1, 0);
请注意,如果 VM 内部以不同的格式表示数组,则 GetPrimitiveArrayCritical 可能仍会复制数组。因此,我们需要检查其返回值是否为 NULL,以避免可能的内存不足情况。
LINKAGE(GetPrimitiveArrayCritical):
- JNIEnv 接口函数表中的链接索引 222。
LINKAGE(ReleasePrimitiveArrayCritical):
- JNIEnv 接口函数表中的链接索引 223。
自 JDK/JRE 1.2 开始。