【JNI编程】JNI函数

507 阅读48分钟

本节作为JNI函数的参考部分。它提供了所有JNI功能的完整列表,还提供了JNI函数表的确切布局。

请注意使用术语“必须”来描述对JNI程序员的限制。 例如,当您看到某个JNI函数必须接收非NULL对象时,您有责任确保不将NULL传递给该JNI函数。 因此,JNI实现不需要在该JNI函数中执行NULL指针检查。

本节的一部分改编自Netscape的JRI文档。

参考材料按其用法分组。参考部分由以下功能区域组成:

  • 版本信息
  • Class操作
  • 异常
  • 全局和局部引用
  • 弱全局引用
  • 对象操作
  • 访问对象的字段
  • 调用实例方法
  • 访问静态字段
  • 调用静态方法
  • 字符串操作
  • 数组操作
  • 注册本地方法
  • Monitor操作
  • NIO支持
  • 反射支持
  • JVM接口

一、接口函数表

可以通过JNIEnv参数以固定偏移量访问每个函数。JNIEnv类型是指向存储所有JNI函数指针的结构的指针。 它的定义如下:

typedef const struct JNINativeInterface *JNIEnv; 

VM初始化功能表,如下代码所示。请注意,前三个条目保留用于将来与COM的兼容性。此外,我们在函数表的开头附近保留了一些额外的NULL条目,因此,例如,可以在FindClass之后而不是在表的末尾添加与类相关的未来JNI操作。

请注意,函数表可以在所有JNI接口指针之间共享。

const struct JNINativeInterface ... = {

    NULL,
    NULL,
    NULL,
    NULL,
    GetVersion,

    DefineClass,
    FindClass,

    FromReflectedMethod,
    FromReflectedField,
    ToReflectedMethod,

    GetSuperclass,
    IsAssignableFrom,

    ToReflectedField,

    Throw,
    ThrowNew,
    ExceptionOccurred,
    ExceptionDescribe,
    ExceptionClear,
    FatalError,

    PushLocalFrame,
    PopLocalFrame,

    NewGlobalRef,
    DeleteGlobalRef,
    DeleteLocalRef,
    IsSameObject,
    NewLocalRef,
    EnsureLocalCapacity,

    AllocObject,
    NewObject,
    NewObjectV,
    NewObjectA,

    GetObjectClass,
    IsInstanceOf,

    GetMethodID,

    CallObjectMethod,
    CallObjectMethodV,
    CallObjectMethodA,
    CallBooleanMethod,
    CallBooleanMethodV,
    CallBooleanMethodA,
    CallByteMethod,
    CallByteMethodV,
    CallByteMethodA,
    CallCharMethod,
    CallCharMethodV,
    CallCharMethodA,
    CallShortMethod,
    CallShortMethodV,
    CallShortMethodA,
    CallIntMethod,
    CallIntMethodV,
    CallIntMethodA,
    CallLongMethod,
    CallLongMethodV,
    CallLongMethodA,
    CallFloatMethod,
    CallFloatMethodV,
    CallFloatMethodA,
    CallDoubleMethod,
    CallDoubleMethodV,
    CallDoubleMethodA,
    CallVoidMethod,
    CallVoidMethodV,
    CallVoidMethodA,

    CallNonvirtualObjectMethod,
    CallNonvirtualObjectMethodV,
    CallNonvirtualObjectMethodA,
    CallNonvirtualBooleanMethod,
    CallNonvirtualBooleanMethodV,
    CallNonvirtualBooleanMethodA,
    CallNonvirtualByteMethod,
    CallNonvirtualByteMethodV,
    CallNonvirtualByteMethodA,
    CallNonvirtualCharMethod,
    CallNonvirtualCharMethodV,
    CallNonvirtualCharMethodA,
    CallNonvirtualShortMethod,
    CallNonvirtualShortMethodV,
    CallNonvirtualShortMethodA,
    CallNonvirtualIntMethod,
    CallNonvirtualIntMethodV,
    CallNonvirtualIntMethodA,
    CallNonvirtualLongMethod,
    CallNonvirtualLongMethodV,
    CallNonvirtualLongMethodA,
    CallNonvirtualFloatMethod,
    CallNonvirtualFloatMethodV,
    CallNonvirtualFloatMethodA,
    CallNonvirtualDoubleMethod,
    CallNonvirtualDoubleMethodV,
    CallNonvirtualDoubleMethodA,
    CallNonvirtualVoidMethod,
    CallNonvirtualVoidMethodV,
    CallNonvirtualVoidMethodA,

    GetFieldID,

    GetObjectField,
    GetBooleanField,
    GetByteField,
    GetCharField,
    GetShortField,
    GetIntField,
    GetLongField,
    GetFloatField,
    GetDoubleField,
    SetObjectField,
    SetBooleanField,
    SetByteField,
    SetCharField,
    SetShortField,
    SetIntField,
    SetLongField,
    SetFloatField,
    SetDoubleField,

    GetStaticMethodID,

    CallStaticObjectMethod,
    CallStaticObjectMethodV,
    CallStaticObjectMethodA,
    CallStaticBooleanMethod,
    CallStaticBooleanMethodV,
    CallStaticBooleanMethodA,
    CallStaticByteMethod,
    CallStaticByteMethodV,
    CallStaticByteMethodA,
    CallStaticCharMethod,
    CallStaticCharMethodV,
    CallStaticCharMethodA,
    CallStaticShortMethod,
    CallStaticShortMethodV,
    CallStaticShortMethodA,
    CallStaticIntMethod,
    CallStaticIntMethodV,
    CallStaticIntMethodA,
    CallStaticLongMethod,
    CallStaticLongMethodV,
    CallStaticLongMethodA,
    CallStaticFloatMethod,
    CallStaticFloatMethodV,
    CallStaticFloatMethodA,
    CallStaticDoubleMethod,
    CallStaticDoubleMethodV,
    CallStaticDoubleMethodA,
    CallStaticVoidMethod,
    CallStaticVoidMethodV,
    CallStaticVoidMethodA,

    GetStaticFieldID,

    GetStaticObjectField,
    GetStaticBooleanField,
    GetStaticByteField,
    GetStaticCharField,
    GetStaticShortField,
    GetStaticIntField,
    GetStaticLongField,
    GetStaticFloatField,
    GetStaticDoubleField,

    SetStaticObjectField,
    SetStaticBooleanField,
    SetStaticByteField,
    SetStaticCharField,
    SetStaticShortField,
    SetStaticIntField,
    SetStaticLongField,
    SetStaticFloatField,
    SetStaticDoubleField,

    NewString,

    GetStringLength,
    GetStringChars,
    ReleaseStringChars,

    NewStringUTF,
    GetStringUTFLength,
    GetStringUTFChars,
    ReleaseStringUTFChars,

    GetArrayLength,

    NewObjectArray,
    GetObjectArrayElement,
    SetObjectArrayElement,

    NewBooleanArray,
    NewByteArray,
    NewCharArray,
    NewShortArray,
    NewIntArray,
    NewLongArray,
    NewFloatArray,
    NewDoubleArray,

    GetBooleanArrayElements,
    GetByteArrayElements,
    GetCharArrayElements,
    GetShortArrayElements,
    GetIntArrayElements,
    GetLongArrayElements,
    GetFloatArrayElements,
    GetDoubleArrayElements,

    ReleaseBooleanArrayElements,
    ReleaseByteArrayElements,
    ReleaseCharArrayElements,
    ReleaseShortArrayElements,
    ReleaseIntArrayElements,
    ReleaseLongArrayElements,
    ReleaseFloatArrayElements,
    ReleaseDoubleArrayElements,

    GetBooleanArrayRegion,
    GetByteArrayRegion,
    GetCharArrayRegion,
    GetShortArrayRegion,
    GetIntArrayRegion,
    GetLongArrayRegion,
    GetFloatArrayRegion,
    GetDoubleArrayRegion,
    SetBooleanArrayRegion,
    SetByteArrayRegion,
    SetCharArrayRegion,
    SetShortArrayRegion,
    SetIntArrayRegion,
    SetLongArrayRegion,
    SetFloatArrayRegion,
    SetDoubleArrayRegion,

    RegisterNatives,
    UnregisterNatives,

    MonitorEnter,
    MonitorExit,

    GetJavaVM,

    GetStringRegion,
    GetStringUTFRegion,

    GetPrimitiveArrayCritical,
    ReleasePrimitiveArrayCritical,

    GetStringCritical,
    ReleaseStringCritical,

    NewWeakGlobalRef,
    DeleteWeakGlobalRef,

    ExceptionCheck,

    NewDirectByteBuffer,
    GetDirectBufferAddress,
    GetDirectBufferCapacity,

    GetObjectRefType
  };

二、版本信息

GetVersion

jint GetVersion(JNIEnv *env);

返回本地方法接口的版本。

LINKAGE:

JNIEnv接口函数表中的索引4。

PARAMETERS:

env:JNI接口指针。

RETURNS:

返回高16位的主版本号和低16位的次版本号。

在JDK/JRE 1.1中,GetVersion()返回0x00010001。

在JDK/JRE 1.2中,GetVersion()返回0x00010002。

在JDK/JRE 1.4中,GetVersion()返回0x00010004。

在JDK/JRE 1.6中,GetVersion()返回0x00010006。

常量

SINCE JDK/JRE 1.2:

#define JNI_VERSION_1_1 0x00010001
#define JNI_VERSION_1_2 0x00010002

/* Error codes */
#define JNI_EDETACHED    (-2)              /* thread detached from the VM */
#define JNI_EVERSION     (-3)              /* JNI version error 

SINCE JDK/JRE 1.4:

#define JNI_VERSION_1_4 0x00010004

SINCE JDK/JRE 1.6:

#define JNI_VERSION_1_6 0x00010006

三、Class操作

3.1 DefineClass

jclass DefineClass(JNIEnv *env, const char *name, jobject loader,
const jbyte *buf, jsize bufLen);

从原始类数据的缓冲区加载一个类。在DefineClass调用返回后,VM不会引用包含原始类数据的缓冲区,如果需要,可以将其丢弃。

LINKAGE:

JNIEnv接口函数表中的索引5。

PARAMETERS:

env:JNI接口指针。

name:要定义的类或接口的名称,该字符串使用修改后的UTF-8编码。

loader:分配给已定义类的类加载器。

buf:包含.class文件数据的缓冲区。

bufLen:缓冲区长度。

RETURNS:

如果发生错误,则返回Java类对象或NULL。

THROWS:

ClassFormatError:如果类数据未指定有效类。

ClassCircularityError:如果类或接口是它自己的超类或超接口。

OutOfMemoryError:如果系统内存不足。

SecurityException:如果调用者尝试在“java”包树中定义一个类。

3.2 FindClass

jclass FindClass(JNIEnv *env, const char *name);

在JDK 1.1版本中,这个函数加载一个本地定义的类。它在CLASSPATH环境变量指定的目录和zip文件中搜索具有指定名称的类。

从Java 2 SDK 1.2版开始,Java安全模型允许非系统类加载和调用本地方法。FindClass定位与当前本地方法关联的类加载器;也就是说,声明本地方法的类的类加载器。如果本地方法属于系统类,则不涉及类加载器。否则,否则,将调用适当的类加载器来加载和链接指定的类。

从Java 2 SDK 1.2版开始,当通过调用接口调用FindClass时,没有当前的本地方法或其关联的类加载器。在这种情况下,使用ClassLoader.getSystemClassLoader的结果。这是虚拟机为应用程序创建的类加载器,并且能够定位java.class.path属性中列出的类。

name参数是完全限定的类名或数组类型签名。 例如,java.lang.String类的完全限定类名是:“java/lang/String”

数组类java.lang.Object []的数组类型签名是:"[Ljava/lang/Object;"

LINKAGE:

JNIEnv接口函数表中的索引6。

PARAMETERS:

env:JNI接口指针。

name:完全限定的类名(即包名,由“/”分隔,后跟类名)。如果名称以“[”(数组签名字符)开头,则返回数组类。该字符串以修改后的UTF-8编码。

RETURNS:

从完全限定名称返回类对象,如果找不到类,则返回NULL。

THROWS:

ClassFormatError:如果类数据未指定有效类。

ClassCircularityError:如果类或接口是它自己的超类或超接口。

NoClassDefFoundError:如果找不到所请求的类或接口的定义。

OutOfMemoryError:如果系统内存不足。

3.3 GetSuperclass

jclass GetSuperclass(JNIEnv *env, jclass clazz);

如果clazz表示除Object类之外的任何类,则此函数返回表示clazz指定的类的超类的对象。

如果clazz指定类Object,或者clazz表示接口,则此函数返回NULL。

LINKAGE:

JNIEnv接口函数表中的索引10。

PARAMETERS:

env:JNI接口指针。

clazz:一个Java类对象。

RETURNS:

返回clazz表示的类的超类,或NULL。

3.4 IsAssignableFrom

jboolean IsAssignableFrom(JNIEnv *env, jclass clazz1, jclass clazz2);

确定clazz1的对象是否可以安全地转换为clazz2。

LINKAGE:

JNIEnv接口函数表中的索引11。

PARAMETERS:

env:JNI接口指针。

clazz1:第一个类参数。

clazz2:第二个类参数。

RETURNS:

如果满足以下任一条件,则返回JNI_TRUE:

  • 第一个和第二个类参数引用相同的Java类。
  • 第一个类是第二个类的子类。
  • 第一个类将第二个类作为其接口之一。

四、异常

4.1 Throw

jint Throw(JNIEnv *env, jthrowable obj);

导致抛出java.lang.Throwable对象。

LINKAGE:

JNIEnv接口函数表中的索引13。

PARAMETERS:

env:JNI接口指针。

obj:一个java.lang.Throwable对象。

RETURNS:

成功时返回0; 失败时为负值。

THROWS:

java.lang.Throwable对象obj。

4.2 ThrowNew

jint ThrowNew(JNIEnv *env, jclass clazz, const char *message);

使用message指定的消息从指定的类构造一个异常对象,并导致抛出该异常。

LINKAGE:

JNIEnv接口函数表中的索引14。

PARAMETERS:

env:JNI接口指针。

clazz:java.lang.Throwable的子类。

message:用于构造java.lang.Throwable对象的消息。该字符串以修改后的UTF-8编码。

RETURNS:

成功时返回0; 失败时为负值。

THROWS:

新构造的java.lang.Throwable对象。

4.3 ExceptionOccurred

jthrowable ExceptionOccurred(JNIEnv *env);

确定是否抛出异常。在本地代码调用ExceptionClear()或Java代码处理异常之前,异常会一直抛出。

LINKAGE:

JNIEnv接口函数表中的索引15。

PARAMETERS:

env:JNI接口指针。

RETURNS:

返回当前正在抛出的异常对象,如果当前没有抛出异常,则返回NULL。

4.4 ExceptionDescribe

void ExceptionDescribe(JNIEnv *env);

将堆栈的异常和回溯打印到系统错误报告通道,例如stderr。这是为调试提供的便利例程。

LINKAGE:

JNIEnv接口函数表中的索引16。

PARAMETERS:

env:JNI接口指针。

4.5 ExceptionClear

void ExceptionClear(JNIEnv *env);

清除当前正在抛出的任何异常。 如果当前没有抛出异常,则此例程无效。

LINKAGE:

JNIEnv接口函数表中的索引17。

PARAMETERS:

env:JNI接口指针。

4.6 FatalError

void FatalError(JNIEnv *env, const char *msg);

引发致命错误,并且不希望VM恢复。此功能不返回。

LINKAGE:

JNIEnv接口函数表中的索引18。

PARAMETERS:

env:JNI接口指针。

msg:错误消息。该字符串以修改后的UTF-8编码。

4.7 ExceptionCheck

我们引入了一个便捷函数来检查挂起的异常,而不创建对异常对象的局部引用。

jboolean ExceptionCheck(JNIEnv *env);

存在挂起异常时返回JNI_TRUE; 否则,返回JNI_FALSE。

LINKAGE:

JNIEnv接口函数表中的索引228。

SINCE:

JDK/JRE 1.2

五、全局和局部引用

5.1 全局引用

5.1.1 NewGlobalRef

jobject NewGlobalRef(JNIEnv *env, jobject obj);

创建对obj参数引用的对象的新全局引用。obj参数可以是全局或局部引用。必须通过调用DeleteGlobalRef()显式处理全局引用。

LINKAGE:

JNIEnv接口函数表中的索引21。

PARAMETERS:

env:JNI接口指针。

obj:全局或局部引用。

RETURNS:

返回全局引用,如果系统内存不足,则返回NULL。

5.1.2 DeleteGlobalRef

void DeleteGlobalRef(JNIEnv *env, jobject globalRef);

删除globalRef指向的全局引用。

LINKAGE:

JNIEnv接口函数表中的索引22。

PARAMETERS:

env:JNI接口指针。

globalRef:全局引用。

5.2 局部引用

局部引用在本地方法调用的持续时间内有效。它们在本地方法返回后自动释放。每个局部引用都会花费一定量的Java虚拟机资源。 程序员需要确保本地方法不会过度分配局部引用。尽管在本地方法返回到Java之后会自动释放局部引用,但过度分配局部引用可能会导致VM在执行本地方法期间耗尽内存。

5.2.1 DeleteLocalRef

void DeleteLocalRef(JNIEnv *env, jobject localRef);

删除localRef指向的局部引用。

LINKAGE:

JNIEnv接口函数表中的索引23。

PARAMETERS:

env:JNI接口指针。

localRef:局部引用。

请注意

JDK/JRE 1.1提供了上面的DeleteLocalRef函数,程序员可以手动删除局部引用。例如,如果本地代码遍历一个可能很大的对象数组并在每次迭代中使用一个元素,那么在下一次迭代中创建新的局部引用之前,最好删除对不再使用的数组元素的局部引用。

从JDK/JRE 1.2开始,为局部引用生命周期管理提供了一组额外的函数。它们是下面列出的四个函数。

5.2.2 EnsureLocalCapacity

jint EnsureLocalCapacity(JNIEnv *env, jint capacity);

确保在当前线程中至少可以创建给定数量的局部引用。 成功返回0;否则返回一个负数并抛出OutOfMemoryError。

在进入本地方法之前,VM自动确保至少可以创建16个局部引用。

为了向后兼容,VM分配超出保证容量的局部引用(作为调试支持,VM可能会警告用户创建了太多的局部引用。在JDK中,程序员可以使用-verbose:jni命令行选项来打开这些消息)。如果不能在保证的容量之外创建更多的局部引用,VM将调用FatalError。

LINKAGE:

JNIEnv接口函数表中的索引26。

SINCE:

JDK/JRE 1.2

5.2.3 PushLocalFrame

jint PushLocalFrame(JNIEnv *env, jint capacity);

创建一个新的局部引用框架,其中至少可以创建给定数量的局部引用。成功时返回0,失败时返回负数和挂起的OutOfMemoryError。

请注意,已在先前本地帧中创建的局部引用在当前本地帧中仍然有效。

LINKAGE:

JNIEnv接口函数表中的索引19。

SINCE:

JDK/JRE 1.2

5.2.4 PopLocalFrame

jobject PopLocalFrame(JNIEnv *env, jobject result);

弹出当前局部引用框架,释放所有局部引用,并在给定结果对象的先前局部引用框架中返回局部引用。

如果您不需要返回对前一帧的引用,则将NULL作为结果传递。

LINKAGE:

JNIEnv接口函数表中的索引20。

SINCE:

JDK/JRE 1.2

5.2.5 NewLocalRef

jobject NewLocalRef(JNIEnv *env, jobject ref);

创建引用与ref相同的对象的新局部引用。给定的引用可以是全局引用或局部引用。如果ref引用NULL,则返回NULL。

LINKAGE:

JNIEnv接口函数表中的索引25。

SINCE:

JDK/JRE 1.2

六、弱全局引用

弱全局引用是一种特殊的全局引用。与普通的全局引用不同,弱全局引用允许对底层Java对象进行垃圾回收。在使用全局或局部引用的任何情况下都可以使用弱全局引用。当垃圾收集器运行时,如果该对象仅由弱引用引用,则它释放底层对象。指向释放对象的弱全局引用在功能上等效于NULL。程序员可以通过使用IsSameObject将弱引用与NULL进行比较来检测弱全局引用是否指向释放的对象。

JNI中的弱全局引用是Java弱引用的简化版本,可作为Java 2 Platform API(java.lang.ref包及其类)的一部分提供。

澄清(2001年6月增加)

由于在本地方法运行时可能会发生垃圾回收,因此可以随时释放由弱全局引用引用的对象。虽然可以在使用全局引用的地方使用弱全局引用,但这样做通常是不合适的,因为它们可能在功能上等同于NULL而不另行通知。

虽然IsSameObject可用于确定弱全局引用是否引用已释放的对象,但它并不阻止随后立即释放该对象。因此,程序员可能不依赖于此检查来确定弱全局引用是否可以在将来的任何JNI函数调用中使用(作为非空引用)。

为了克服这个固有的限制,建议使用JNI函数NewLocalRef或NewGlobalRef获取对同一对象的标准(强)局部或全局引用,并使用该强引用访问目标对象。如果对象已被释放,这些函数将返回NULL,否则将返回一个强引用(这会阻止对象被释放)。当不再需要立即访问该对象时,应该显式地删除新引用,从而允许释放该对象。

弱全局引用弱于其他类型的弱引用(SoftReference或WeakReference类的Java对象)。在引用同一特定对象的SoftReference或WeakReference对象清除其引用之前,对特定对象的弱全局引用在功能上不会等效于NULL。

弱全局引用弱于Java对需要终结的对象的内部引用。在完成引用对象的终结(如果存在)之前,弱全局引用将不会在功能上等效于NULL。

弱全局引用和虚引用之间的交互没有定义。具体来说,JVM的实现可以(也可以不)在虚引用之后处理弱全局引用,并且可以(也可以不)使用弱全局引用来保留也由虚引用对象引用的对象。应该避免使用这种未定义的弱全局引用。

6.1 NewWeakGlobalRef

jweak NewWeakGlobalRef(JNIEnv *env, jobject obj);

创建一个新的弱全局引用。 如果obj引用null,或者VM内存不足,则返回NULL。如果VM内存不足,将抛出OutOfMemoryError。

LINKAGE:

JNIEnv接口函数表中的索引226。

SINCE:

JDK/JRE 1.2

6.2 DeleteWeakGlobalRef

void DeleteWeakGlobalRef(JNIEnv *env, jweak obj);

删除给定弱全局引用所需的VM资源。

LINKAGE:

JNIEnv接口函数表中的索引227。

SINCE:

JDK/JRE 1.2

七、对象操作

7.1 AllocObject

jobject AllocObject(JNIEnv *env, jclass clazz);

在不调用对象的任何构造函数的情况下分配新的Java对象,返回对象的引用。clazz参数不能引用数组类。

LINKAGE:

JNIEnv接口函数表中的索引27。

PARAMETERS:

env:JNI接口指针。

clazz:一个Java类对象。

RETURNS:

返回一个Java对象,如果无法构造该对象,则返回NULL。

THROWS:

InstantiationException:如果类是接口或抽象类。

OutOfMemoryError:如果系统内存不足。

7.2 NewObject, NewObjectA, NewObjectV

jobject NewObject(JNIEnv *env, jclass clazz, jmethodID methodID, ...);

jobject NewObjectA(JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);

jobject NewObjectV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);

构造一个新的Java对象。方法ID指示调用哪个构造函数方法。这个ID必须通过调用GetMethodID()来获得,方法名是,返回类型是void (V)。clazz参数不能引用数组类。

NewObject

程序员将所有要传递给构造函数的参数紧跟在methodID参数之后。NewObject()接受这些参数并将它们传递给程序员希望调用的Java方法。

LINKAGE:

JNIEnv接口函数表中的索引28。

NewObjectA

程序员将传递给构造函数的所有参数放在jvalues的args数组中,该数组紧跟methodID参数。NewObjectA()接受这个数组中的参数,然后将它们传递给程序员希望调用的Java方法。

LINKAGE:

JNIEnv接口函数表中的索引30。

NewObjectV

程序员将传递给构造函数的所有参数放在类型为va_list的args参数中,该参数紧跟methodID参数之后。NewObjectV()接受这些参数,然后将它们传递给程序员希望调用的Java方法。

LINKAGE:

JNIEnv接口函数表中的索引29。

PARAMETERS:

env:JNI接口指针。

clazz:一个Java类对象。

methodID:构造函数的方法ID。

NewObject的附加参数:构造函数的参数。

NewObjectA的附加参数:args:构造函数的参数数组。

NewObjectV的附加参数:args:构造函数的参数的va_list。

RETURNS:

返回一个Java对象,如果无法构造该对象,则返回NULL。

THROWS:

InstantiationException:如果类是接口或抽象类。

OutOfMemoryError:如果系统内存不足。

构造函数抛出的任何异常。

7.3 GetObjectClass

jclass GetObjectClass(JNIEnv *env, jobject obj);

返回对象的class。

LINKAGE:

JNIEnv接口函数表中的索引31。

PARAMETERS:

env:JNI接口指针。

obj:一个Java对象(不能为NULL)。

RETURNS:

返回一个Java类对象。

7.4 GetObjectRefType

jobjectRefType GetObjectRefType(JNIEnv* env, jobject obj);

返回obj参数引用的对象的类型。参数obj可以是局部、全局或弱全局引用。

LINKAGE:

JNIEnv接口函数表中的索引232。

PARAMETERS:

env:JNI接口指针。

obj:局部,全局或弱全局引用。

vm:将从中检索接口的虚拟机实例。

env:指向当前线程的JNI接口指针所在位置的指针。

version:请求的JNI版本。

RETURNS:

函数GetObjectRefType返回以下定义为jobjectRefType的枚举值之一:

JNIInvalidRefType = 0,
JNILocalRefType = 1,
JNIGlobalRefType = 2,
JNIWeakGlobalRefType = 3

如果参数obj是弱全局引用类型,则返回将为JNIWeakGlobalRefType。

如果参数obj是全局引用类型,则返回值将为JNIGlobalRefType。

如果参数obj是局部引用类型,则返回将为JNILocalRefType。

如果obj参数不是有效引用,则此函数的返回值将为JNIInvalidRefType。

无效引用是指不是有效句柄的引用。也就是说,obj指针地址不指向从Ref创建函数中分配的或从JNI函数返回的内存中的位置。

因此,NULL将是无效的引用,GetObjectRefType(env,NULL)将返回JNIInvalidRefType。

另一方面,null引用(指向null的引用)将返回null引用最初创建时的引用类型。

无法在删除的引用上使用GetObjectRefType。

由于引用通常实现为指向内存数据结构的指针,这些结构可能会被VM中的任何引用分配服务重用,因此一旦删除,就不会指定GetObjectRefType将返回什么值。

SINCE:

JDK/JRE 1.6

7.5 IsInstanceOf

jboolean IsInstanceOf(JNIEnv *env, jobject obj, jclass clazz);

测试对象是否是类的实例。

LINKAGE:

JNIEnv接口函数表中的索引32。

PARAMETERS:

env:JNI接口指针。

obj:一个Java对象。

clazz:一个Java类对象。

RETURNS:

如果obj可以转换为clazz,则返回JNI_TRUE; 否则,返回JNI_FALSE。可以将NULL对象强制转换为任何类。

7.6 IsSameObject

jboolean IsSameObject(JNIEnv *env, jobject ref1, jobject ref2);

测试两个引用是否引用相同的Java对象。

LINKAGE:

JNIEnv接口函数表中的索引24。

PARAMETERS:

env:JNI接口指针。

ref1:一个Java对象。

ref2:一个Java对象。

RETURNS:

如果ref1和ref2引用相同的Java对象,则返回JNI_TRUE,或者都是NULL; 否则,返回JNI_FALSE。

八、访问对象的字段

8.1 GetFieldID

jfieldID GetFieldID(JNIEnv *env, jclass clazz, const char *name, const char *sig);

返回类的实例(非静态)字段的字段ID。该字段由其名称和签名指定。访问者函数的GetField和SetField系列使用字段ID来检索对象字段。

GetFieldID()导致未初始化的类被初始化。

GetFieldID()不能用于获取数组的长度字段,使用GetArrayLength()代替。

LINKAGE:

JNIEnv接口函数表中的索引94。

PARAMETERS:

env:JNI接口指针。

clazz:一个Java类对象。

name:以0结尾的修改后的UTF-8字符串中的字段名称。

sig:以0结尾的修改后UTF-8字符串中的字段签名。

RETURNS:

返回字段ID,如果操作失败,则返回NULL。

THROWS:

NoSuchFieldError:如果找不到指定的字段。

ExceptionInInitializerError:如果类初始化程序因异常而失败。

OutOfMemoryError:如果系统内存不足。

8.2 GetField 系列

NativeType Get<type>Field(JNIEnv *env, jobject obj, jfieldID fieldID);

此系列的访问器例程返回对象的实例(非静态)字段的值。要访问的字段由通过调用GetFieldID()获得的字段ID指定。

下表描述了GetField例程名称和结果类型。您应该使用字段的Java类型替换GetField中的type,或者使用表中的一个实际例程名称,并将NativeType替换为该例程的相应本地类型。

GetField例程名称本地类型
GetObjectField()jobject
GetBooleanField()jboolean
GetByteField()jbyte
GetCharField()jchar
GetShortField()jshort
GetIntField()jint
GetLongField()jlong
GetFloatField()jfloat
GetDoubleField()jdouble

表-GetField系列的访问程序例程

LINKAGE:

JNIEnv接口函数表中的索引:

GetField例程名称索引
GetObjectField()95
GetBooleanField()96
GetByteField()97
GetCharField()98
GetShortField()99
GetIntField()100
GetLongField()101
GetFloatField()102
GetDoubleField()103

表-GetField系列的访问程序例程

PARAMETERS:

env:JNI接口指针。

obj:一个Java对象(不能为NULL)。

fieldID:有效的字段ID。

RETURNS:

返回字段的内容。

8.3 SetField 系列

void Set<type>Field(JNIEnv *env, jobject obj, jfieldID fieldID, NativeType value);

此系列的访问器例程设置对象的实例(非静态)字段的值。要访问的字段由通过调用GetFieldID()获得的字段ID指定。

下表描述了SetField例程名称和值类型。你应该将SetField中的type替换为字段的Java类型,或者使用表中的一个实际例程名称,并将NativeType替换为该例程的相应本地类型。

SetField例程本地类型
SetObjectField()jobject
SetBooleanField()jboolean
SetByteField()jbyte
SetCharField()jchar
SetShortField()jshort
SetIntField()jint
SetLongField()jlong
SetFloatField()jfloat
SetDoubleField()jdouble

表-SetField系列的访问程序例程

LINKAGE:

JNIEnv接口函数表中的索引。

SetField例程索引
SetObjectField()104
SetBooleanField()105
SetByteField()106
SetCharField()107
SetShortField()108
SetIntField()109
SetLongField()110
SetFloatField()111
SetDoubleField()112

表-SetField系列的访问程序例程

PARAMETERS:

env:JNI接口指针。

obj:一个Java对象(不能为NULL)。

fieldID:有效的字段ID。

value:字段的新值。

九、调用实例方法

9.1 GetMethodID

jmethodID GetMethodID(JNIEnv *env, jclass clazz, const char *name, const char *sig);

返回类或接口的实例(非静态)方法的方法ID。方法可以在clazz的一个超类中定义,并由clazz继承。方法由其名称和签名决定。

GetMethodID()导致未初始化的类被初始化。

要获取构造函数的方法ID,提供作为方法名,并使用void(V)作为返回类型。

LINKAGE:

JNIEnv接口函数表中的索引33。

PARAMETERS:

env:JNI接口指针。

clazz:一个Java类对象。

name:以0结尾的修改后的UTF-8字符串中的方法名称。

sig:以0结尾的修改的UTF-8字符串中的方法签名。

RETURNS:

返回方法ID,如果找不到指定的方法,则返回NULL。

THROWS:

NoSuchMethodError:如果找不到指定的方法。

ExceptionInInitializerError:如果类初始化程序因异常而失败。

OutOfMemoryError:如果系统内存不足。

9.2 CallMethod、CallMethodA、CallMethodV

NativeType Call<type>Method(JNIEnv *env, jobject obj, jmethodID methodID, ...);

NativeType Call<type>MethodA(JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);

NativeType Call<type>MethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args);

来自这三个操作系列的方法用于从本地方法调用Java实例方法。它们只是将参数传递给它们调用的方法的机制不同。

这些操作系列根据指定的方法ID在Java对象上调用实例(非静态)方法。必须通过调用GetMethodID()获取methodID参数。

当这些函数用于调用私有方法和构造函数时,方法ID必须从obj的真实类派生,而不是从其超类之一派生。

CallMethod 例程

程序员将所有要传递给方法的参数放在紧接methodID参数之后。CallMethod例程接受这些参数,并将它们传递给程序员希望调用的Java方法。

CallMethodA 例程

程序员将该方法的所有参数放在jvalues的args数组中,该数组紧跟methodID参数。CallMethodA例程接受这个数组中的参数,然后将它们传递给程序员希望调用的Java方法。

CallMethodV 例程

程序员将方法的所有参数放在类型为va_list的args参数中,该参数紧跟methodID参数之后。CallMethodV例程接受参数,然后将它们传递给程序员希望调用的Java方法。

下表根据结果类型描述了每个方法调用例程。您应该将CallMethod中的类型替换为您正在调用的方法的Java类型(或者使用表中实际的方法调用例程名称之一),并将NativeType替换为该例程的相应本地类型。

CallMethod例程名称本地类型
CallVoidMethod() CallVoidMethodA() CallVoidMethodV()void
CallObjectMethod() CallObjectMethodA() CallObjectMethodV()jobject
CallBooleanMethod() CallBooleanMethodA() CallBooleanMethodV()jboolean
CallByteMethod() CallByteMethodA() CallByteMethodV()jbyte
CallCharMethod() CallCharMethodA() CallCharMethodV()jchar
CallShortMethod() CallShortMethodA() CallShortMethodV()jshort
CallIntMethod() CallIntMethodA() CallIntMethodV()jint
CallLongMethod() CallLongMethodA() CallLongMethodV()jlong
CallFloatMethod() CallFloatMethodA() CallFloatMethodV()jfloat
CallDoubleMethod() CallDoubleMethodA() CallDoubleMethodV()jdouble

表-实例方法调用例程

LINKAGE:

JNIEnv接口函数表中的索引:

CallMethod例程名称索引
CallVoidMethod() CallVoidMethodA() CallVoidMethodV()61 63 62
CallObjectMethod() CallObjectMethodA() CallObjectMethodV()34 36 35
CallBooleanMethod() CallBooleanMethodA() CallBooleanMethodV()37 39 38
CallByteMethod() CallByteMethodA() CallByteMethodV()40 42 41
CallCharMethod() CallCharMethodA() CallCharMethodV()43 45 44
CallShortMethod() CallShortMethodA() CallShortMethodV()46 48 47
CallIntMethod() CallIntMethodA() CallIntMethodV()49 51 50
CallLongMethod() CallLongMethodA() CallLongMethodV()52 54 53
CallFloatMethod() CallFloatMethodA() CallFloatMethodV()55 57 56
CallDoubleMethod() CallDoubleMethodA() CallDoubleMethodV()58 60 59

表-实例方法调用例程

PARAMETERS:

env:JNI接口指针。

obj:一个Java对象。

methodID:方法ID。

CallMethod例程的附加参数

Java方法的参数。

CallMethodA例程的附加参数

args:一组参数。

CallMethodV例程的附加参数

args:一个参数的va_list。

RETURNS:

返回调用Java方法的结果。

THROWS:

执行Java方法期间引发的异常。

9.3 CallNonvirtualMethod、CallNonvirtualMethodA、CallNonvirtualMethodV

NativeType CallNonvirtual<type>Method(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);

NativeType CallNonvirtual<type>MethodA(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, const jvalue *args);

NativeType CallNonvirtual<type>MethodV(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args);

这些操作系列根据指定的类和方法ID在Java对象上调用实例(非静态)方法。必须通过在类clazz上调用GetMethodID()来获取methodID参数。

CallNonvirtualMethod系列例程和CallMethod系列例程是不同的。CallMethod例程根据对象的类调用方法,而CallNonvirtualMethod例程根据clazz参数指定的类调用方法,从该类中获得方法ID。方法ID必须从对象的实际类或其超类之一获得。

CallNonvirtualMethod 例程

程序员将所有要传递给方法的参数紧跟在methodID参数之后。CallNonvirtualMethod例程接受这些参数并将它们传递给程序员希望调用的Java方法。

CallNonvirtualMethodA 例程

程序员将方法的所有参数放在紧跟在methodID参数之后的jvalues的args数组中。CallNonvirtualMethodA例程接受此数组中的参数,然后将它们传递给程序员希望调用的Java方法。

CallNonvirtualMethodV 例程

程序员将方法的所有参数放在紧跟在methodID参数之后的类型为va_list的args参数中。CallNonvirtualMethodV例程接受参数,然后将它们传递给程序员希望调用的Java方法。

下表根据结果类型描述了每个方法调用例程。您应该将CallNonvirtualMethod中的type替换为方法的Java类型,或者使用表中实际的方法调用例程名称之一,并将NativeType替换为该例程的相应本地类型。

CallNonvirtualMethod 例程名称本地类型
CallNonvirtualVoidMethod() CallNonvirtualVoidMethodA() CallNonvirtualVoidMethodV()void
CallNonvirtualObjectMethod() CallNonvirtualObjectMethodA() CallNonvirtualObjectMethodV()jobject
CallNonvirtualBooleanMethod() CallNonvirtualBooleanMethodA() CallNonvirtualBooleanMethodV()jboolean
CallNonvirtualByteMethod() CallNonvirtualByteMethodA() CallNonvirtualByteMethodV()jbyte
CallNonvirtualCharMethod() CallNonvirtualCharMethodA() CallNonvirtualCharMethodV()jchar
CallNonvirtualShortMethod() CallNonvirtualShortMethodA() CallNonvirtualShortMethodV()jshort
CallNonvirtualIntMethod() CallNonvirtualIntMethodA() CallNonvirtualIntMethodV()jint
CallNonvirtualLongMethod() CallNonvirtualLongMethodA() CallNonvirtualLongMethodV()jlong
CallNonvirtualFloatMethod() CallNonvirtualFloatMethodA() CallNonvirtualFloatMethodV()jfloat
CallNonvirtualDoubleMethod() CallNonvirtualDoubleMethodA() CallNonvirtualDoubleMethodV()jdouble

表-CallNonvirtualMethod例程

LINKAGE:

JNIEnv接口函数表中的索引。

CallNonvirtualMethod 例程名称索引
CallNonvirtualVoidMethod() CallNonvirtualVoidMethodA() CallNonvirtualVoidMethodV()91 93 92
CallNonvirtualObjectMethod() CallNonvirtualObjectMethodA() CallNonvirtualObjectMethodV()64 66 65
CallNonvirtualBooleanMethod() CallNonvirtualBooleanMethodA() CallNonvirtualBooleanMethodV()67 69 68
CallNonvirtualByteMethod() CallNonvirtualByteMethodA() CallNonvirtualByteMethodV()70 72 71
CallNonvirtualCharMethod() CallNonvirtualCharMethodA() CallNonvirtualCharMethodV()73 75 74
CallNonvirtualShortMethod() CallNonvirtualShortMethodA() CallNonvirtualShortMethodV()76 78 77
CallNonvirtualIntMethod() CallNonvirtualIntMethodA() CallNonvirtualIntMethodV()79 81 80
CallNonvirtualLongMethod() CallNonvirtualLongMethodA() CallNonvirtualLongMethodV()82 84 83
CallNonvirtualFloatMethod() CallNonvirtualFloatMethodA() CallNonvirtualFloatMethodV()85 87 86
CallNonvirtualDoubleMethod() CallNonvirtualDoubleMethodA() CallNonvirtualDoubleMethodV()88 90 89

表-CallNonvirtualMethod例程

PARAMETERS:

env:JNI接口指针。

clazz:一个Java类。

obj:一个Java对象。

methodID:方法ID。

CallNonvirtualMethod例程的附加参数:
Java方法的参数。

CallNonvirtualMethodA例程的附加参数:
args:一组参数。

CallNonvirtualMethodV例程的附加参数:
args:一个参数的va_list。

RETURNS:

返回调用Java方法的结果。

THROWS:

Java方法执行过程中引发的异常。

十、访问静态字段

10.1 GetStaticFieldID

jfieldID GetStaticFieldID(JNIEnv *env, jclass clazz, const char *name, const char *sig);

返回类的静态字段的字段ID。字段由其名称和签名指定。访问器函数的GetStaticField和SetStaticField 系列使用字段id检索静态字段。

GetStaticFieldID()导致未初始化的类被初始化。

LINKAGE:

JNIEnv接口函数表中的索引144。

PARAMETERS:

env:JNI接口指针。

clazz:一个Java类对象。

name:以0结尾的修改后的UTF-8字符串中的静态字段名称。

sig:以0结尾的修改后的UTF-8字符串中的字段签名。

RETURNS:

返回字段ID,如果找不到指定的静态字段,则返回NULL。

THROWS:

NoSuchFieldError:如果找不到指定的静态字段。

ExceptionInInitializerError:如果类初始化程序因异常而失败。

OutOfMemoryError:如果系统内存不足。

10.2 GetStaticField

NativeType GetStatic<type>Field(JNIEnv *env, jclass clazz, jfieldID fieldID);

这个访问器例程系列返回对象的静态字段的值。要访问的字段由字段ID指定,该字段ID是通过调用GetStaticFieldID()获得的。

下表描述了get例程名称和结果类型的系列。您应该将GetStaticField中的type替换为该字段的Java类型,或者替换该表中的一个实际静态字段访问者例程名称,并将NativeType替换为该例程的相应本地类型。

GetStaticField例程名称本地类型
GetStaticObjectField()jobject
GetStaticBooleanField()jboolean
GetStaticByteField()jbyte
GetStaticCharField()jchar
GetStaticShortField()jshort
GetStaticIntField()jint
GetStaticLongField()jlong
GetStaticFloatField()jfloat
GetStaticDoubleField()jdouble

LINKAGE:

JNIEnv接口函数表中的索引。

GetStaticField例程名称索引
GetStaticObjectField()145
GetStaticBooleanField()146
GetStaticByteField()147
GetStaticCharField()148
GetStaticShortField()149
GetStaticIntField()150
GetStaticLongField()151
GetStaticFloatField()152
GetStaticDoubleField()153

PARAMETERS:

env:JNI接口指针。

clazz:一个Java类对象。

fieldID:静态字段ID。

RETURNS:

返回静态字段的内容。

10.3 SetStaticField

void SetStatic<type>Field(JNIEnv *env, jclass clazz, jfieldID fieldID, NativeType value);

这类访问器例程设置对象的静态字段的值。要访问的字段由字段ID指定,该ID通过调用GetStaticFieldID()获得。

下表描述了设置的例程名称和值类型。您应该将SetStaticField中的类型替换为该字段的Java类型,或者表中实际设置的静态字段例程名称之一,并将NativeType替换为该例程的相应本地类型。

SetStaticField例程名称本地类型
SetStaticObjectField()jobject
SetStaticBooleanField()jboolean
SetStaticByteField()jbyte
SetStaticCharField()jchar
SetStaticShortField()jshort
SetStaticIntField()jint
SetStaticLongField()jlong
SetStaticFloatField()jfloat
SetStaticDoubleField()jdouble

LINKAGE:

JNIEnv接口函数表中的索引。

SetStaticField例程名称索引
SetStaticObjectField()154
SetStaticBooleanField()155
SetStaticByteField()156
SetStaticCharField()157
SetStaticShortField()158
SetStaticIntField()159
SetStaticLongField()160
SetStaticFloatField()161
SetStaticDoubleField()162

PARAMETERS:

env:JNI接口指针。

clazz:一个Java类对象。

fieldID:静态字段ID。

value:字段的新值。

十一、调用静态方法

11.1 GetStaticMethodID

jmethodID GetStaticMethodID(JNIEnv *env, jclass clazz, const char *name, const char *sig);

返回类的静态方法的方法ID。方法由其名称和签名指定。GetStaticMethodID()导致一个未初始化的类被初始化。

LINKAGE:

JNIEnv接口函数表中的索引113。

PARAMETERS:

env:JNI接口指针。

clazz:Java类对象。

name:以0结尾的修改后的UTF-8字符串中的静态方法名称。

sig:以0结尾的修改后的UTF-8字符串中的方法签名。

RETURNS:

返回方法ID,如果操作失败则返回NULL。

THROWS:

NoSuchMethodError:如果无法找到指定的静态方法。

ExceptionInInitializerError:如果类初始化器由于异常而失败。

OutOfMemoryError:如果系统耗尽内存。

11.2 CallStaticMethod、CallStaticMethodA 、CallStaticMethodV

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对象上调用静态方法。 必须通过调用GetStaticMethodID()获取methodID参数。

方法ID必须来自clazz,而不是来自其中一个超类。

CallStaticMethod

程序员应该将所有要传递给方法的参数紧跟在methodID参数之后。CallStaticMethod例程接受这些参数并将它们传递给程序员希望调用的Java方法。

CallStaticMethodA

程序员应该将方法的所有参数放在紧跟在methodID参数之后的jvalues的args数组中。CallStaticMethodA例程接受此数组中的参数,然后将它们传递给程序员希望调用的Java方法。

CallStaticMethodV

程序员应该将方法的所有参数放在紧跟在methodID参数之后的类型为va_list的args参数中。CallStaticMethodV例程接受参数,然后将它们传递给程序员希望调用的Java方法。

下表根据结果类型描述了每个方法调用例程。您应该将CallStaticMethod中的type替换为方法的Java类型,或者从表中替换实际方法调用例程名称之一,并将NativeType替换为该例程的相应本地类型。

CallStaticMethod例程名称本地类型
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

表-CallStaticMethod调用例程

LINKAGE:

JNIEnv接口函数表中的索引。

CallStaticMethod例程名称索引
CallStaticVoidMethod() CallStaticVoidMethodA() CallStaticVoidMethodV()141 143 142
CallStaticObjectMethod() CallStaticObjectMethodA() CallStaticObjectMethodV()114 116 115
CallStaticBooleanMethod() CallStaticBooleanMethodA() CallStaticBooleanMethodV()117 119 118
CallStaticByteMethod() CallStaticByteMethodA() CallStaticByteMethodV()120 122 121
CallStaticCharMethod() CallStaticCharMethodA() CallStaticCharMethodV()123 125 124
CallStaticShortMethod() CallStaticShortMethodA() CallStaticShortMethodV()126 128 127
CallStaticIntMethod() CallStaticIntMethodA() CallStaticIntMethodV()129 131 130
CallStaticLongMethod() CallStaticLongMethodA() CallStaticLongMethodV()132 134 133
CallStaticFloatMethod() CallStaticFloatMethodA() CallStaticFloatMethodV()135 137 136
CallStaticDoubleMethod() CallStaticDoubleMethodA() CallStaticDoubleMethodV()138 140 139

表-CallStaticMethod调用例程

PARAMETERS:

env:JNI接口指针。

clazz:一个Java类对象。

methodID:静态方法ID。

CallStaticMethod例程的附加参数:
静态方法的参数。

CallStaticMethodA例程的附加参数:
args:一组参数。

CallStaticMethodV例程的附加参数:
args:一个参数的va_list。

RETURNS:

返回调用静态Java方法的结果。

THROWS:

执行Java方法期间引发的异常。

十二、字符串操作

12.1 NewString

jstring NewString(JNIEnv *env, const jchar *unicodeChars, jsize len);

从Unicode字符数组构造一个新的java.lang.String对象。

LINKAGE:

JNIEnv接口函数表中的索引163。

PARAMETERS:

env:JNI接口指针。

unicodeChars:指向Unicode字符串的指针。

len:Unicode字符串的长度。

RETURNS:

返回Java字符串对象,如果无法构造字符串,则返回NULL。

THROWS:

OutOfMemoryError:如果系统内存不足。

12.2 GetStringLength

jsize GetStringLength(JNIEnv *env, jstring string);

返回Java字符串的长度(Unicode字符数)。

LINKAGE:

JNIEnv接口函数表中的索引164。

PARAMETERS:

env:JNI接口指针。

string:Java字符串对象。

RETURNS:

返回Java字符串的长度。

12.3 GetStringChars

const jchar * GetStringChars(JNIEnv *env, jstring string, jboolean *isCopy);

返回指向字符串的Unicode字符数组的指针。在调用ReleaseStringchars()之前,此指针有效。

如果isCopy不为NULL,如果进行了复制,则*isCopy设置为JNI_TRUE; 如果没有复制,则设置为JNI_FALSE。

LINKAGE:

JNIEnv接口函数表中的索引165。

PARAMETERS:

env:JNI接口指针。

string:Java字符串对象。

isCopy:指向布尔值的指针。

RETURNS:

返回指向Unicode字符串的指针,如果操作失败,则返回NULL。

12.4 ReleaseStringChars

void ReleaseStringChars(JNIEnv *env, jstring string, const jchar *chars);

通知VM本地代码不再需要访问字符。chars参数是使用GetStringChars()从字符串获取的指针。

LINKAGE:

JNIEnv接口函数表中的索引166。

PARAMETERS:

env:JNI接口指针。

string:Java字符串对象。

chars:指向Unicode字符串的指针。

12.5 NewStringUTF

jstring NewStringUTF(JNIEnv *env, const char *bytes);

从修改后的UTF-8编码中的字符数组构造一个新的java.lang.String对象。

LINKAGE:

JNIEnv接口函数表中的索引167。

PARAMETERS:

env:JNI接口指针。

bytes:指向修改后的UTF-8字符串的指针。

RETURNS:

返回Java字符串对象,如果无法构造字符串,则返回NULL。

THROWS:

OutOfMemoryError:如果系统内存不足。

12.6 GetStringUTFLength

jsize GetStringUTFLength(JNIEnv *env, jstring string);

返回字符串的修改后的UTF-8表示的字节长度。

LINKAGE:

JNIEnv接口函数表中的索引168。

PARAMETERS:

env:JNI接口指针。

string:Java字符串对象。

RETURNS:

返回字符串的UTF-8长度。

12.7 GetStringUTFChars

const char * GetStringUTFChars(JNIEnv *env, jstring string, jboolean *isCopy);

返回指向字节数组的指针,该字节数组表示修改后的UTF-8编码中的字符串。此数组在ReleaseStringUTFChars()释放之前有效。

如果isCopy不为NULL,如果进行了复制,则*isCopy设置为JNI_TRUE; 如果没有复制,则设置为JNI_FALSE。

LINKAGE:

JNIEnv接口函数表中的索引169。

PARAMETERS:

env:JNI接口指针。

string:Java字符串对象。

isCopy:指向布尔值的指针。

RETURNS:

返回指向修改后的UTF-8字符串的指针,如果操作失败,则返回NULL。

12.8 ReleaseStringUTFChars

void ReleaseStringUTFChars(JNIEnv *env, jstring string, const char *utf);

通知VM本地代码不再需要访问utf。utf参数是使用GetStringUTFChars()从字符串派生的指针。

LINKAGE:

JNIEnv接口函数表中的索引170。

PARAMETERS:

env:JNI接口指针。

string:Java字符串对象。

utf:指向修改后的UTF-8字符串的指针。

注意

在JDK/JRE 1.1中,程序员可以在用户提供的缓冲区中获取原始数组元素。从JDK/JRE 1.2开始,提供了一组额外的功能,允许本地代码在用户提供的缓冲区中获取Unicode(UTF-16)或修改的UTF-8编码的字符。 请参阅以下功能。

12.9 GetStringRegion

void GetStringRegion(JNIEnv *env, jstring str, jsize start, jsize len, jchar *buf);

将偏移量开头处的len个Unicode字符数复制到给定的缓冲区buf。

索引溢出时抛出StringIndexOutOfBoundsException。

LINKAGE:

JNIEnv接口函数表中的索引220。

SINCE:

JDK/JRE 1.2

12.10 GetStringUTFRegion

void GetStringUTFRegion(JNIEnv *env, jstring str, jsize start, jsize len, char *buf);

将从偏移量开始的Unicode字符的len数转换为经过修改的UTF-8编码,并将结果放在给定的缓冲区buf中。

索引溢出时抛出StringIndexOutOfBoundsException。

LINKAGE:

JNIEnv接口函数表中的索引221。

SINCE:

JDK/JRE 1.2

12.11 GetStringCritical、ReleaseStringCritical

const jchar * GetStringCritical(JNIEnv *env, jstring string, jboolean *isCopy);
void ReleaseStringCritical(JNIEnv *env, jstring string, const jchar *carray);

这两个函数的语义类似于现有的Get/ReleaseStringChars函数。如果可能,VM返回指向字符串元素的指针;否则,制作副本。 但是,如何使用这些功能存在重大限制。在Get/ReleaseStringCritical调用包含的代码段中,本地代码不得发出任意JNI调用,或导致当前线程阻塞。

Get/ReleaseStringCritical的限制与Get/ReleasePrimitiveArrayCritical上的限制类似。

LINKAGE (GetStringCritical) :

JNIEnv接口函数表中的索引224。

LINKAGE (ReleaseStingCritical) :

JNIEnv接口函数表中的索引225。

SINCE:

JDK/JRE 1.2

十三、数组操作

13.1 GetArrayLength

jsize GetArrayLength(JNIEnv *env, jarray array);

返回数组中元素的数量。

LINKAGE:

JNIEnv接口函数表中的索引171。

PARAMETERS:

env:JNI接口指针。

array:一个Java数组对象。

RETURNS:

返回数组的长度。

13.2 NewObjectArray

jobjectArray NewObjectArray(JNIEnv *env, jsize length, jclass elementClass, jobject initialElement);

在类elementClass中构造一个包含对象的新数组。所有元素最初都设置为initialElement。

LINKAGE:

JNIEnv接口函数表中的索引172。

PARAMETERS:

env:JNI接口指针。

length:数组大小。

elementClass:数组元素类。

initialElement:初始化值。

RETURNS:

返回Java数组对象,如果数组不能构造,则返回NULL。

THROWS:

OutOfMemoryError:如果系统内存不足。

13.3 GetObjectArrayElement

jobject GetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index);

返回Object数组的元素。

LINKAGE:

JNIEnv接口函数表中的索引173。

PARAMETERS:

env:JNI接口指针。

array:一个Java数组。

index:数组索引。

RETURNS:

返回一个Java对象。

THROWS:

ArrayIndexOutOfBoundsException:如果index未在数组中指定有效索引。

13.4 SetObjectArrayElement

void SetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index, jobject value);

设置Object数组的元素。

LINKAGE:

JNIEnv接口函数表中的索引174。

PARAMETERS:

env:JNI接口指针。

array:一个Java数组。

index:数组索引。

value:新值。

THROWS:

ArrayIndexOutOfBoundsException:如果index未在数组中指定有效索引。

ArrayStoreException: 如果值的类不是数组的元素类的子类。

13.5 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

LINKAGE:

JNIEnv接口函数表中的索引。

NewArray例程Index
NewBooleanArray()175
NewByteArray()176
NewCharArray()177
NewShortArray()178
NewIntArray()179
NewLongArray()180
NewFloatArray()181
NewDoubleArray()182

PARAMETERS:

env:JNI接口指针。

length:数组长度。

RETURNS:

返回Java数组,如果无法构造数组,则返回NULL。

13.6 GetArrayElements

NativeType *Get<PrimitiveType>ArrayElements(JNIEnv *env, ArrayType array, jboolean *isCopy);

返回基本数组主体的一系列函数。结果有效,直到调用相应的ReleaseArrayElements()函数。由于返回的数组可能是Java数组的副本,因此在调用ReleaseArrayElements())之前,对返回数组所做的更改不一定会反映在原始数组中。

如果isCopy不为NULL,如果进行了复制,则*isCopy设置为JNI_TRUE; 如果没有复制,则设置为JNI_FALSE。

下表描述了特定的原始数组元素访问器。您应该进行以下替换:

  • 将GetArrayElements替换为下表中的一个实际原始元素访问器例程名称。
  • 将ArrayType替换为相应的数组类型。
  • 将NativeType替换为该例程的相应本地类型。

无论如何在JVM中表示布尔数组,GetBooleanArrayElements()始终返回指向jbooleans的指针,每个字节表示一个元素(解包表示)。其他类型的所有数组都保证在内存中是连续的。

GetArrayElements例程数组类型本地类型
GetBooleanArrayElements()jbooleanArrayjboolean
GetByteArrayElements()jbyteArrayjbyte
GetCharArrayElements()jcharArrayjchar
GetShortArrayElements()jshortArrayjshort
GetIntArrayElements()jintArrayjint
GetLongArrayElements()jlongArrayjlong
GetFloatArrayElements()jfloatArrayjfloat
GetDoubleArrayElements()jdoubleArrayjdouble

LINKAGE:

JNIEnv接口函数表中的索引。

GetArrayElements例程Index
GetBooleanArrayElements()183
GetByteArrayElements()184
GetCharArrayElements()185
GetShortArrayElements()186
GetIntArrayElements()187
GetLongArrayElements()188
GetFloatArrayElements()189
GetDoubleArrayElements()190

PARAMETERS:

env:JNI接口指针。

array:一个Java字符串对象。

isCopy:指向布尔值的指针。

RETURNS:

返回指向数组元素的指针,如果操作失败则返回NULL。

13.7 ReleaseArrayElements

void Release<PrimitiveType>ArrayElements(JNIEnv *env, ArrayType array, NativeType *elems, jint mode);

一系列函数,通知VM本地代码不再需要访问elems。elems参数是使用相应的GetArrayElements()函数从数组派生的指针。如有必要,此函数会将对elems所做的所有更改复制回原始数组。

mode参数提供有关如何释放数组缓冲区的信息。如果elems不是数组中元素的副本,则mode无效。否则,模式会产生以下影响,如下表所示:

模式行为
0复制回内容并释放elems缓冲区
JNI_COMMIT复制回内容,但不释放elems缓冲区
JNI_ABORT释放缓冲区而不复制回可能的更改

在大多数情况下,程序员将“0”传递给mode参数,以确保固定和复制数组的一致行为。其他选项使程序员可以更好地控制内存管理,并且应该非常谨慎地使用。

下表描述了构成原始数组处理者系列的特定例程。您应该进行以下替换:

  • 将ReleaseArrayElements替换为下表中的一个实际原始数组处理程序例程名称。
  • 将ArrayType替换为相应的数组类型。
  • 将NativeType替换为该例程的相应本地类型。
ReleaseArrayElements数组类型本地类型
ReleaseBooleanArrayElements()jbooleanArrayjboolean
ReleaseByteArrayElements()jbyteArrayjbyte
ReleaseCharArrayElements()jcharArrayjchar
ReleaseShortArrayElements()jshortArrayjshort
ReleaseIntArrayElements()jintArrayjint
ReleaseLongArrayElements()jlongArrayjlong
ReleaseFloatArrayElements()jfloatArrayjfloat
ReleaseDoubleArrayElements()jdoubleArrayjdouble

LINKAGE:

JNIEnv接口函数表中的索引。

ReleaseArrayElements索引
ReleaseBooleanArrayElements()191
ReleaseByteArrayElements()192
ReleaseCharArrayElements()193
ReleaseShortArrayElements()194
ReleaseIntArrayElements()195
ReleaseLongArrayElements()196
ReleaseFloatArrayElements()197
ReleaseDoubleArrayElements()198

PARAMETERS:

env:JNI接口指针。

array:一个Java数组对象。

elems:指向数组元素的指针。

mode:释放模式。

13.8 GetArrayRegion

void Get<PrimitiveType>ArrayRegion(JNIEnv *env, ArrayType array, jsize start, jsize len, NativeType *buf);

一组函数,将原始数组的某个区域复制到缓冲区中。

下表描述了特定的原始数组元素访问器,你应该做以下替换:

  • 将GetArrayRegion替换为下表中的一个实际原始元素访问器例程名称。
  • 将ArrayType替换为相应的数组类型。
  • 将NativeType替换为该例程的相应本地类型。
GetArrayRegion数组类型本地类型
GetBooleanArrayRegion()jbooleanArrayjboolean
GetByteArrayRegion()jbyteArrayjbyte
GetCharArrayRegion()jcharArrayjchar
GetShortArrayRegion()jshortArrayjshort
GetIntArrayRegion()jintArrayjint
GetLongArrayRegion()jlongArrayjlong
GetFloatArrayRegion()jfloatArrayjloat
GetDoubleArrayRegion()jdoubleArrayjdouble

LINKAGE:

JNIEnv接口函数表中的索引。

GetArrayRegion索引
GetBooleanArrayRegion()199
GetByteArrayRegion()200
GetCharArrayRegion()201
GetShortArrayRegion()202
GetIntArrayRegion()203
GetLongArrayRegion()204
GetFloatArrayRegion()205
GetDoubleArrayRegion()206

PARAMETERS:

env:JNI接口指针。

array:一个Java数组。

start:起始索引。

len:要复制的元素数。

buf:目标缓冲区。

THROWS:

ArrayIndexOutOfBoundsException: 如果区域中的某个索引无效。

13.9 SetArrayRegion

void Set<PrimitiveType>ArrayRegion(JNIEnv *env, ArrayType array, jsize start, jsize len, const NativeType *buf);

一组函数,用于从缓冲区中复制回原始数组的某个区域。

下表描述了特定的原始数组元素访问器。您应该进行以下替换:

将SetArrayRegion替换为下表中的一个实际原始元素访问器例程名称。
将ArrayType替换为相应的数组类型。
将NativeType替换为该例程的相应本地类型。

SetArrayRegion数组类型本地类型
SetBooleanArrayRegion()jbooleanArrayjboolean
SetByteArrayRegion()jbyteArrayjbyte
SetCharArrayRegion()jcharArrayjchar
SetShortArrayRegion()jshortArrayjshort
SetIntArrayRegion()jintArrayjint
SetLongArrayRegion()jlongArrayjlong
SetFloatArrayRegion()jfloatArrayjfloat
SetDoubleArrayRegion()jdoubleArrayjdouble

LINKAGE:

JNIEnv接口函数表中的索引。

SetArrayRegion索引
SetBooleanArrayRegion()207
SetByteArrayRegion()208
SetCharArrayRegion()209
SetShortArrayRegion()210
SetIntArrayRegion()211
SetLongArrayRegion()212
SetFloatArrayRegion()213
SetDoubleArrayRegion()214

PARAMETERS:

env:JNI接口指针。

array:一个Java数组。

start:起始索引。

len:要复制的元素数。

buf:源缓冲区。

THROWS:

ArrayIndexOutOfBoundsException: 如果区域中的某个索引无效。

注意

从JDK/JRE 1.1开始,程序员可以使用Get/ReleaseArrayElements函数来获取指向原始数组元素的指针。如果VM支持固定,则返回指向原始数据的指针; 否则,制作副本。从JDK/JRE 1.3开始引入的新功能允许本地代码获取指向数组元素的直接指针,即使VM不支持固定。

13.10 GetPrimitiveArrayCritical、ReleasePrimitiveArrayCritical

void * GetPrimitiveArrayCritical(JNIEnv *env, jarray array, jboolean *isCopy);
void ReleasePrimitiveArrayCritical(JNIEnv *env, jarray array, void *carray, jint mode);

这两个函数的语义非常类似于现有的Get/ReleaseArrayElements函数。如果可能,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);
  /* 我们需要检查VM是否尝试制作副本。 */
  if (a1 == NULL || a2 == NULL) {
    ... /* 抛出内存异常 */
  }
  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。

SINCE:

JDK/JRE 1.2

十四、注册本地方法

14.1 RegisterNatives

jint RegisterNatives(JNIEnv *env, jclass clazz, const JNINativeMethod *methods, jint nMethods);

使用clazz参数指定的类注册本地方法。methods参数指定JNINativeMethod结构的数组,其中包含本地方法的名称,签名和函数指针。 JNINativeMethod结构的名称和签名字段是指向修改后的UTF-8字符串的指针。nMethods参数指定数组中的本地方法数。JNINativeMethod结构定义如下:

typedef struct { 

    char *name; 

    char *signature; 

    void *fnPtr; 

} JNINativeMethod; 

函数指针在名义上必须有以下签名:

ReturnType (*fnPtr)(JNIEnv *env, jobject objectOrClass, ...); 

LINKAGE:

JNIEnv接口函数表中的索引215。

PARAMETERS:

env:JNI接口指针。

clazz:一个Java类对象。

methods:类中的本地方法。

nMethods:类中本地方法的数量。

RETURNS:

成功时返回“0”; 失败时返回负值。

THROWS:

NoSuchMethodError: 如果找不到指定的方法或该方法不是本地方法。

14.2 UnregisterNatives

jint UnregisterNatives(JNIEnv *env, jclass clazz);

取消注册类的本地方法。该类返回到它与其本地方法函数链接或注册之前的状态。

此函数不应在普通本地代码中使用。相反,它为特殊程序提供了重新加载和重新链接本地库的方法。

LINKAGE:

JNIEnv接口函数表中的索引216。

PARAMETERS:

env:JNI接口指针。

clazz:一个Java类对象。

RETURNS:

成功时返回“0”; 失败时返回负值。

十五、Monitor操作

15.1 MonitorEnter

jint MonitorEnter(JNIEnv *env, jobject obj);

进入与obj引用的底层Java对象相关联的监视器。

每个Java对象都有一个与之关联的监视器。如果当前线程已经拥有与obj关联的监视器,它会增加监视器中的计数器,指示此线程进入监视器的次数。 如果与obj关联的监视器不属于任何线程,则当前线程将成为监视器的所有者,将此监视器的条目计数设置为1。如果另一个线程已拥有与obj关联的监视器,则当前线程将等待,直到监视器被释放,然后再次尝试获得所有权。

通过MonitorEnter JNI函数调用进入的监视器无法使用monitorexit Java虚拟机指令或synchronized方法返回退出。 MonitorEnter JNI函数调用和monitorenter Java虚拟机指令可能竞争进入与同一对象关联的监视器。

为避免死锁,必须使用MonitorExit JNI调用退出通过MonitorEnter JNI函数调用进入的监视器,除非使用DetachCurrentThread调用来隐式释放JNI监视器。

LINKAGE:

JNIEnv接口函数表中的索引217。

PARAMETERS:

env:JNI接口指针。

obj:普通的Java对象或类对象。

RETURNS:

成功返回“0”;失败时返回负值。

15.2 MonitorExit

jint MonitorExit(JNIEnv *env, jobject obj);

当前线程必须是与obj引用的底层Java对象关联的监视器的所有者。线程递减计数器,指示它进入此监视器的次数。如果计数器的值变为零,则当前线程释放监视器。

本地代码不得使用MonitorExit退出通过synchronized方法或monitorenter Java虚拟机指令进入的监视器。

LINKAGE:

JNIEnv接口函数表中的索引218。

PARAMETERS:

env:JNI接口指针。

obj:普通的Java对象或类对象。

RETURNS:

成功时返回“0”; 失败时返回负值。

EXCEPTIONS:

IllegalMonitorStateException: 如果当前线程不拥有监视器。

十六、NIO支持

与NIO相关的入口点允许本地代码访问java.nio直接缓冲区。直接缓冲区的内容可能存在于普通垃圾收集堆之外的本地内存中。有关直接缓冲区的信息,请参阅New I/O APIs和java.nio.ByteBuffer类的规范。

JDK/JRE 1.4中引入的三个新函数允许JNI代码创建、检查和操作直接缓冲区:

  • NewDirectByteBuffer
  • GetDirectBufferAddress
  • GetDirectBufferCapacity

Java虚拟机的每个实现都必须支持这些功能,但并不是每个实现都需要支持对直接缓冲区的JNI访问。如果JVM不支持此类访问,则NewDirectByteBuffer和GetDirectBufferAddress函数必须始终返回NULL,并且GetDirectBufferCapacity函数必须始终返回-1。 如果JVM确实支持此类访问,则必须实现这三个函数以返回适当的值。

16.1 NewDirectByteBuffer

jobject NewDirectByteBuffer(JNIEnv* env, void* address, jlong capacity);

分配并返回一个直接的java.nio.ByteBuffer,它指的是从内存地址address开始并扩展capacity字节的内存块。

调用此函数并将生成的字节缓冲区对象返回到Java级代码的本地代码应确保缓冲区引用可供读取的内存的有效区域,并在适当时写入。尝试从Java代码访问无效的内存位置将返回任意值,没有可见效果,或导致抛出未指定的异常。

LINKAGE:

JNIEnv接口函数表中的索引229。

PARAMETERS:

env:JNIEnv接口指针

address:内存区域的起始地址(不能为NULL)

capacity:内存区域的大小(以字节为单位)(必须为正)

RETURNS:

返回对新实例化的java.nio.ByteBuffer对象的局部引用。如果发生异常,或者此虚拟机不支持对直接缓冲区的JNI访问,则返回NULL。

EXCEPTIONS:

OutOfMemoryError: 如果ByteBuffer对象的分配失败

SINCE:

JDK/JRE 1.4

16.2 GetDirectBufferAddress

void* GetDirectBufferAddress(JNIEnv* env, jobject buf);

获取并返回给定直接java.nio.Buffer引用的内存区域的起始地址。

此函数允许本地代码通过缓冲区对象访问Java代码可访问的相同内存区域。

LINKAGE:

JNIEnv接口函数表中的索引230。

PARAMETERS:

env:JNIEnv接口指针

buf:一个直接的java.nio.Buffer对象(不能为NULL)

RETURNS:

返回缓冲区引用的内存区域的起始地址。如果内存区域未定义,如果给定对象不是直接java.nio.Buffer,或者此虚拟机不支持对直接缓冲区的JNI访问,则返回NULL。

SINCE:

JDK/JRE 1.4

16.3 GetDirectBufferCapacity

jlong GetDirectBufferCapacity(JNIEnv* env, jobject buf);

获取并返回给定直接java.nio.Buffer引用的内存区域的容量。容量是内存区域包含的元素数。

LINKAGE:

JNIEnv接口函数表中的索引231。

PARAMETERS:

env:JNIEnv接口指针

buf:一个直接的java.nio.Buffer对象(不能为NULL)

RETURNS:

返回与缓冲区关联的内存区域的容量。 如果给定对象不是直接java.nio.Buffer,如果对象是未对齐的视图缓冲区且处理器体系结构不支持未对齐访问,或者此虚拟机不支持对直接缓冲区的JNI访问,则返回-1。

SINCE:

JDK/JRE 1.4

十七、反射支持

如果程序员知道方法或字段的名称和类型,他们可以使用JNI来调用Java方法或访问Java字段。 Java Core Reflection API允许程序员在运行时内省Java类。 JNI在JNI中使用的字段和方法ID之间提供了一组转换函数,用于Java Core Reflection API中使用的字段和方法对象。

17.1 FromReflectedMethod

jmethodID FromReflectedMethod(JNIEnv *env, jobject method);

将java.lang.reflect.Method或java.lang.reflect.Constructor对象转换为方法ID。

LINKAGE:

JNIEnv接口函数表中的索引7。

SINCE:

JDK/JRE 1.2

17.2 FromReflectedField

jfieldID FromReflectedField(JNIEnv *env, jobject field);

将java.lang.reflect.Field转换为字段ID。

LINKAGE:

JNIEnv接口函数表中的索引8。

SINCE:

JDK/JRE 1.2

17.3 ToReflectedMethod

jobject ToReflectedMethod(JNIEnv *env, jclass cls, jmethodID methodID, jboolean isStatic);

将从cls派生的方法ID转换为java.lang.reflect.Method或java.lang.reflect.Constructor对象。如果方法ID引用静态字段,则isStatic必须设置为JNI_TRUE,否则设置为JNI_FALSE。

抛出OutOfMemoryError,如果失败则返回0。

LINKAGE:

JNIEnv接口函数表中的索引9。

SINCE:

JDK/JRE 1.2

17.4 ToReflectedField

jobject ToReflectedField(JNIEnv *env, jclass cls, jfieldID fieldID, jboolean isStatic);

将从cls派生的字段ID转换为java.lang.reflect.Field对象。如果fieldID引用静态字段,则isStatic必须设置为JNI_TRUE,否则设置为JNI_FALSE。

抛出OutOfMemoryError,如果失败则返回0。

LINKAGE:

JNIEnv接口函数表中的索引12。

SINCE:

JDK/JRE 1.2

十八、JVM接口

18.1 GetJavaVM

jint GetJavaVM(JNIEnv *env, JavaVM **vm);

返回与当前线程关联的Java VM接口(在Invocation API中使用)。 结果放在第二个参数vm指向的位置。

LINKAGE:

JNIEnv接口函数表中的索引219。

PARAMETERS:

env:JNI接口指针。

vm:指向结果放置位置的指针。

RETURNS:

成功返回“0”;失败时返回负值。