一、需求
需要频繁的调用jni实现java、native的数据传递,数据回调给android端做渲染。
把数据直接放到native,减少native的调用, 用到java的java.nio包。在项目中主要使用的是ByteBuffer
ByteBuffer内存共享分为两种:1、java栈内存共享 2、native堆申请内存。
由于native和java的内存不在 一个空间,为了共享,必须为一个空间,在native申请内存,IO性能 会更好,也即DirectByteBuff
二、DirectByteBuffer的使用
1. native创建DirectByteBuffer,java通过native映射
优点:封装实现
缺点:ByteBuffer一些接口不可以使用,如array(),获取数据需要调用jni接口进行拷贝
Java1.4版本引入JNI有三个函数可以用户NIO的直接缓存器。一个直接字节缓冲器是一个用于字节的容器,Java尽量在它上面执行本机的I/O操作。
/* 基于到存储器地址的指针以及存储器长度(容量),函数分配并且返回一个新的Java.nio.ByteBuffer。如果函数没有针对当前Java虚拟机实现,则返回NULL,或者抛出一个异常。如果没有存储器可用,则将会抛出一个OutOfMemoryException。*/
jobject NewDirectByteBuffer(void* address, jlong capacity);
/* GetDirectBufferAddress函数返回一个指向被传入的java.nio.ByteBuffer对象的地址指针。如果函数尚未针对当前虚拟机实现,或者如果buf不是java.nio.ByteBuffer的一个对象,又或者存储器区尚未定义,则都将返回NULL。*/
void* GetDirectBufferAddress(jobject buf);
/*GetDirectBufferCapacity函数返回被传入的java.nio.ByteBuffer对象的容量(以字节计数)。如果函数没有针对当前环境实现,或者如果buf不是java.nio.ByteBuffer类型的对象返回-1。*/
jlong GetDirectBufferCapacity(jobject buf);
3.1Jni中调用
Java层:
public final int processData(ByteBuffer data);
Native 接口:
private native long native_Process(ByteBuffer data);
Jni层:
static jlong native_Process(JNIEnv *env, jobject obj,jobject data);
注意ByteBuffer在JNI层中的签名:Ljava/nio/ByteBuffer;
eg(C++):
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[];
https://blog.csdn.net/windgs_yf/article/details/104051188
4、ByteBuffer操作及使用
slice() //浅拷贝
copy()//深拷贝
frame.position(y_position);
frame.limit(uPos);
ByteBuffer dataY = frame.slice();
https://blog.csdn.net/xiaoninvhuang/article/details/70827856
一、火焰图
网友评论