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的一个接口。