The quiter you become,the more you are able to hear!

JNI官方文档-Chapter 4:JNI Functions

Author: geneblue

Blog: https://geneblue.github.io/

本章主要作为JNI函数的参考手册。这里提供完整的JNI函数列表,也提供JNI函数表的设计。

注意“必须”这个词常常描述对JNI开发人员的限制。如,当你看到一个JNI函数“必须”接收一个非空的对象时,你就要确保NULL值不会被传递到该JNI函数。所以,该JNI函数的实现是不需要执行NULL值检查的。

本章有一部分是改编自Netscape的JRI文档。

参考材料以用途来划分,参考段落以如下功能来区分:

  • Version Information
  • Class Operations
  • Exceptions
  • Global and Local Reference
  • Weak Global References
  • Object Operations
  • Accessing Fields of Objects
  • Calling Instance Methods
  • Accessing Static Fields
  • Calling Static Methods
  • String Operations
  • Array Operations
  • Registering Native Methods
  • Monitor Operations
  • NIO Support
  • Reflection Support
  • Java VM Interface

Interface Function Table

每一个函数都可以通过JNIEnv参数以固定的偏移获取。JNIEnv类型是一个指针,该指针指向一个结构体,结构体中存储着所有的JNI函数指针。该类型以如下形式定义:

typedef const struct JNINativeInterface *JNIEnv;

JVM会初始化函数表,函数表参见代码示例4-1。注意最开始的三个入口点是为了将来与COM保持兼容性而保留的。此外,我们在函数表的开始处保留一些NULL入口点,所以在将来如果有与JNI操作相关的类就可以添加在FindClass后,而不是在函数表的最后。

注意,函数表是被所有的JNI接口指针共享的。

Code Example 4-1:

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
};

Version Information

GetVersion

jint GetVersion(JNIEnv *env);

返回native方法接口的版本信息。

LINKAGE:

  • JNIEnv接口函数表的序号为4(0为起始序号)。

PARAMETERS:

  • env:JNI接口指针。

RETURNS:

  • 高16位返回主版本号,低16位返回副版本号。 In JDK/JRE 1.1, GetVersion() returns 0x00010001. In JDK/JRE 1.2, GetVersion() returns 0x00010002. In JDK/JRE 1.4, GetVersion() returns 0x00010004. In JDK/JRE 1.6, GetVersion() returns 0x00010006.

Constants:

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 Operations

DefineClass

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

从一个保存原始类数据的buffer中加载一个类。在DefineClass函数被调用后,该buffer并不会被JVM引用,如果需要的话,该buffer还有可能被丢弃。

LINKAGE:

  • JNIEnv接口函数表的序号为5。

PARAMETERS:

  • env:JNI接口指针。
  • name:类名或接口定义的名字,Modified UTF-8编码。
  • loader:加载该类的类加载器。
  • buf:保存.class文件数据的buffer。
  • bufLen:buffer的长度。

RETURNS:

  • 返回java类对象或NULL。

THROWS:

  • ClassFormatError:当类数据不是合法的类时
  • ClassCircularityError:当类或接口成为自身的父类或父接口时
  • OutOfMemoryError:当系统运行时候,内存溢出
  • SecurityException:当调用者试图在“java”包树中定义类时

FindClass

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

在JDK发行版1.1中,该函数加载一个本地定义的类。函数通过指定的类名搜索由系统环境变量指定的目录和zip文件。

自Java 2 SDK的1.2版本以来,java安全模型允许非系统类来加载和调用native方法。FindClass函数会定位与现有native方法相关的类加载器,也就是声明native方法类的类加载器。如果native方法属于一个系统类,没有加载器会去与之关联。相反,合适的类加载器会去加载类名指定的类。

自Java 2 SDK的1.2版本以来,当FindClass函数通过调用接口被调用时,就不会有现行的native方法和关联的类加载器。在那种情况下,ClassLoader.getSystemClassLoader会被调用。这个是VM创建应用程序是使用的类加载器,该加载器能够定位java.class.path属性中列出的类。

参数name是类的全名或一个类数组的类型签名。如,对java.lang.String的类的全名是:“java/lang/String”。对java.lang.Object[]的数组签名就是:“[Ljava/lang/Object”。

LINKAGE:

  • JNIEnv接口函数表的序号为6。

PARAMETERS:

  • env:JNI接口指针。
  • name:类的全名或类数组的类型签名,Modified UTF-8编码。

RETURNS:

  • 返回类对象或NULL。

THROWS:

  • ClassFormatError:当类数据不是合法的类时
  • ClassCircularityError:当类或接口成为自身的父类或父接口时
  • NoClassDefFoundErrot:当类未定义或查找不到时
  • OutOfMemoryError:当系统运行时候,内存溢出

GetSuperClass

jclass GetSuperclass(JNIEnv *env, jclass clazz);

如果clazz表示任意的类而不是类对象,那该函数会返回clazz指定类的父类的对象。

如果clazz是一个确定的类对象,或表示一个接口,那该函数返回NULL。

LINKAGE:

  • JNIEnv接口函数表的序号为10。

PARAMETERS:

  • env:JNI接口指针。
  • clazz:一个java类对象。

RETURNS:

  • 返回clazz指定的类的父类或NULL。

IsAssignableFrom

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

判定clazz1对象能否安全地转换为clazz2对象。

LINKAGE:

  • JNIEnv接口函数表的序号为11。

PARAMETERS:

  • env:JNI接口指针。
  • clazz1:第一个类参数。
  • clazz2:第二个类参数。

RETURNS:

  • 下面任意一个情况为真时就返回JNI_TRUE:
  • clazz1和clazz2指向同样的java类。
  • clazz1是clazz2的子类。
  • clazz2是clazz1的一个接口。