您的位置:首页 > 其它

【安卓开发】JNI常用接口 - 5

2016-01-31 22:05 411 查看
11、注册本地方法

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

根据clazz参数注册本地方法,methods参数指定JNINativeMethod 结构数组,该数组包含本地方法的名字、签名及函数指针。其中名字及签名是指向modified UTF-8的指针;nMethods 参数表明数组中本地方法的个数。

typedef struct {

char *name;

char *signature;

void *fnPtr;

} JNINativeMethod;

fnPtr通常有以下的签名

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

参数:

env:JNI接口指针

clazz:java类对象

methods:类中的本地方法

nMethods:类中本地方法的个数

返回:

成功返回0,失败返回负数

异常:

NoSuchMethodError:如果没有指定的方法或者该方法不是本地的。

jint UnregisterNatives(JNIEnv *env, jclass clazz);

注销本地方法。类回归之前还没被函数注册的状态。

该函数把不能在一般的本地代码中被调用,它为特定的程序提供了一种重加载重连接本地库的方法。

参数:

env:JNI接口指针

clazz:java类对象

返回:

成功返回0,失败返回负数。

12、监视器操作

jint MonitorEnter(JNIEnv *env, jobject obj);

进入被obj引用的底层java对象关联的监视器。obj引用不能为空。

每个java对象都有一个相关的监视器。如果当前线程已经有关联至obj的监视器,它将增加监视器的计数器来表明这个线程进入监视器的次数。如果关联至obj的监视器不属于任何线程,那当前线程将变成该监视器的拥有者,并设置计数为1.如果其他计数器已经拥有这个监视器,当前线程将进行等待直到监视器被释放,然后再获得监视器的拥有权。

通过MonitorEnter Jni函数调用的监视器不能用 monitorexit Java虚拟机指令或者同步方法 退出。MonitorEnter Jni函数调用和 monitorenter Java虚拟机指令可能用同样的对象竞争地进入监视器

为了避免死锁,通过MoniterEnter Jni函数调用进入的监视器必须用MonitorExit Jni调用退出,除非DetachCurrentThread接口被调用隐式的释放Jni监视器。

参数:

env:JNI接口指针

obj:普通的java对象或类对象

返回:

成功返回0,失败返回负数

jint MonitorExit(JNIEnv *env, jobject obj);

当前线程必须拥有该与obj关联的监视器,线程减少计数器的值来指示线程进入监视器的次数。如果计数器的值变成0,但钱线程释放该监视器。

本地代码不能使用MonitorExit来退出通过同步方法或者monitorenter Java虚拟机指令进入的监视器

参数:

env:JNI接口指针

obj:普通的java对象或类对象

返回:

成功返回0,失败返回负数

异常:

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

13、NIO支持

NIO相关的接入点允许本地代码访问java.nio direct buffer。direct buffer内容可以留驻在原来垃圾回收器的堆之外的本地内存。

所有的JAVA虚拟机必须支持这些函数:

NewDirectByteBuffer

GetDirectBufferAddress

GetDirectBufferCapacity

来创建、检测及操作direct buffer。

但并不是每个实现都必须支持JNI访问direct buffer。如果虚拟机不支持访问direct buffer,NewDirectByteBuffer 及GetDirectBufferAddress函数必须返回NULL,GetDirectBufferCapacity 返回-1.如果JVM支持,则返回对应的值。

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

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

调用这个函数并返回字节缓存区的对象的本地代码必须保证缓冲区指向一个可靠的可被读写的内存区域。进入非法的内存位置有可能会返回任意数值,但不会有明显的影响,也有可能抛出异常。

参数:

env:JNIEnv接口指针

address:内存区域的起始地址

capacity:内存区域的大小。

返回:

返回一个新开辟的java.nio.ByteBuffer 对象的本地引用。返回NULL如果产生异常或者JVM不支持JNI访问direct buffer

异常:

OutOfMemoryError :如果缓冲区分配失败。

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

获取并返回java.nio.Buffer的内存初始地址。

该函数允许本地代码访问能够被java代码通过buffer对象访问的相同的内存空间。

参数:

env:JNIEnv接口指针

buf:java.nio.Buffer对象

返回:

返回内存区域的初始地址。如果内存区域未定义,返回NULL,如果给定的对象不是java.nio.buffer,或者虚拟机不支持JNI访问返回NULL。

jlong GetDirectBufferCapacity(JNIEnv* env, jobject buf);

获取并返回java.nio.Buffer的内存容量。该容量是内存区域可容纳的元素的个数

参数:

env:JNIEnv接口指针

buf:java.nio.Buffer对象

返回:

返回内存区域的容量。如果给定的对象不是java.nio.buffer,返回-1,或者如果对象是未对齐的view buffer 且处理器架构不支持未对齐访问。或者虚拟机不支持JNI访问返回-1。

Reflection Support

编程者如果知道方法或者域的名字及类型,可使用JNI调用JAVA方法或者访问java域。java反射API允许编程者在运行时反视java类。jni在提供了转换函数集,从JNI中的域及方法IDs到JAVA反射API中的域及方法。

jmethodID FromReflectedMethod(JNIEnv *env, jobject method);

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

jfieldID FromReflectedField(JNIEnv *env, jobject field);

将java.lang.reflect.Field转换为域ID

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

如果失败返回0,并且抛出OutOfMemoryError

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

将来源于cls的域ID转化为java.lang.reflect.Field 对象。如果域ID指向一个静态域,isStatic必须设置为JNI_TRUE ,否则为JNI_FALSE

如果失败返回0,并且抛出OutOfMemoryError

15、JAVA 虚拟机接口

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

返回当前线程对应的java虚拟机接口。返回的结果保存在vm。

参数:

env:JNI接口指针

vm:保存虚拟机指针

返回:

成功返回0,失败返回负数
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: