本文实例讲述了Android在JNI中使用ByteBuffer的方法。分享给大家供大家参考。具体如下:
一、ByteBuffer 定义
在NIO中,数据的读写操作始终是与缓冲区相关联的(读取时信道(SocketChannel)将数据读入缓冲区,写入时首先要将发送的数据按顺序填入缓冲区)
缓冲区是定长的,基本上它只是一个列表,它的所有元素都是基本数据类型。ByteBuffer是最常用的缓冲区,它提供了读写其他数据类型的方法,且信道的读写方法只接收ByteBuffer。
ByteBuffer有以下几种常见属性:
mark:初始值为-1,标记索引地点;
position:初始值为0,索引下标;
limit:最好定义成bytebuffer的长度,即允许可读空间长度;
capacity:缓冲区能容纳的数据元素的最大数量,创建之后无法被改变;
二、ByteBuffer使用
1. 创建ByteBuffer
① 使用allocate()创建:
1
2
|
ByteBuffer buf = ByteBuffer.allocate(length); //length表示buf的长度 |
② 使用数组创建:
1
2
|
ByteBuffer buf = ByteBuffer.wrap(byteArray); //byteArray表示一个数组 |
2. 回绕缓冲区
1
|
buf.flip(); |
这个方法用来将缓冲区准备为数据传出状态,执行以上方法后,输出通道会从数据的开头而不是末尾开始.回绕保持缓冲区中的数据不变,只是准备写入而不是读取。
3. 清除缓冲区
1
|
buf.clear(); |
这个方法实际上也不会改变缓冲区的数据,而只是简单的重置了缓冲区的主要索引值.不必为了每次读写都创建新的缓冲区,那样做会降低性能.相反,要重用现在的缓冲区,在再次读取之前要清除缓冲区。
4. ByteBuffer与byte[]交互
1
2
3
4
5
6
7
|
byte [] bytearray = new byte [ 10 ]; ByteBuffer buf = ByteBuffer.wrap(bytearray); //将数组写入buf bytearray = new byte [buf.remaining()]; buf.get(bytearray, 0 ,bytearray.length()); //将数据读到数组中 bytearray = new byte [buf.capacity()]; |
三、ByteBuffer与JNI交互
在Java1.4版本中引入的JNI有三个函数可以用于NIO的直接缓冲器。一个直接字节缓冲器是一个用于字节数据的容器,Java将尽力在它上面执行本机I/O操作。JNI定义了三个用于NIO操作的函数。
基于到存储器地址的指针以及存储器长度(容量),函数分配并且返回一个新的Java.nio.ByteBuffer。如果函数没有针对当前Java虚拟机实现,则返回NULL,或者抛出一个异常。如果没有存储器可用,则将会抛出一个OutOfMemoryException。
1
|
jobject NewDirectByteBuffer( void * address, jlong capacity); |
GetDirectBufferAddress函数返回一个指向被传入的java.nio.ByteBuffer对象的地址指针。如果函数尚未针对当前虚拟机实现,或者如果buf不是java.nio.ByteBuffer的一个对象,又或者存储器区尚未定义,则都将返回NULL。
1
|
void * GetDirectBufferAddress(jobject buf); |
GetDirectBufferCapacity函数返回被传入的java.nio.ByteBuffer对象的容量(以字节计数)。如果函数没有针对当前环境实现,或者如果buf不是java.nio.ByteBuffer类型的对象返回-1。
1
|
jlong GetDirectBufferCapacity(jobject buf); |
1. Jni中调用
Java层:
1
|
public final int processData(ByteBuffer data); |
Native 接口:
1
|
private native long native_Process(ByteBuffer data); |
Jni层:
1
|
static jlong native_Process(JNIEnv *env,jobject obj,jobject data); |
注意ByteBuffer在JNI层中的签名:Ljava/nio/ByteBuffer;
2. 示例(C++):
1
2
3
4
5
|
jclass cls = env->GetObjectClass(obj); jfieldID fid = env->GetFieldID(cls, "data" , "Ljava/nio/ByteBuffer;" ); jobject bar = env->GetObjectField(obj, fid); pImageData->data= (MByte*)env->GetDirectBufferAddress(bar); //data是结构体pImageData中的byte[]; |
希望本文所述对大家的Android程序设计有所帮助。