我在java中有一个对象数组,我想允许原生c代码直接访问该数组(没有复制或访问函数)。这可能吗?我不介意解决方案是否针对jvm。
szqfcxe21#
当然,使用jni是可能的。值得参考以下链接:http://journals.ecs.soton.ac.uk/java/tutorial/native1.1/implementing/array.html 总之-
# include <jni.h> # include "IntArray.h" JNIEXPORT jint JNICALL Java_IntArray_sumArray(JNIEnv *env, jobject obj, jintArray arr) { jsize len = (*env)->GetArrayLength(env, arr); int i, sum = 0; jint *body = (*env)->GetIntArrayElements(env, arr, 0); for (i=0; i<len; i++) sum += body[i]; (*env)->ReleaseIntArrayElements(env, arr, body, 0); return sum; }
bvk5enib2#
我终于找到了答案。一般来说,用jni做我想做的事情是不可能的。但是,有些虚拟机提供了所需的功能,我使用了jikesrvm:1) 本机代码需要数组的内存位置。这可以通过使用jikesrvm中的“magic”工具来实现,它提供了一个objectreference和一个address类,允许为每个对象获取一个内存地址。然后,这个地址可以作为long/int参数(使用jni)转发到本机代码,并在那里强制转换到指针。2) gc不能移动对象。这有点棘手,因为它需要在gc中支持固定。在jikesrvm的情况下,可以用@nonmoving和@nonmovingallocation(也是“magic”的一部分)对对象进行注解。此外,大于8kb的对象(即数组)被放置在一个大的对象空间中,这样就不会移动对象。
qlfbtfca3#
如果您使用的是较新版本的java,请使用bytebuffer对象。呼叫 ByteBuffer.allocateDirect() 分配缓冲区。直接缓冲区位于垃圾收集器的域之外。要从jni访问缓冲区,请调用 GetDirectBufferAddress() . 它返回一个指向字节缓冲区的指针。这不能在引擎盖下复制。对缓冲区的更改将在java和本机端看到。javadocs对使用直接缓冲区有一些警告:可以通过调用此类的allocatedirect工厂方法来创建直接字节缓冲区。此方法返回的缓冲区通常比非直接缓冲区具有更高的分配和释放成本。直接缓冲区的内容可能位于正常垃圾收集堆之外,因此它们对应用程序内存占用的影响可能并不明显。因此,建议将直接缓冲区主要分配给受底层系统本机i/o操作影响的大型长寿命缓冲区。一般来说,只有当直接缓冲区在程序性能上产生可测量的增益时,才最好分配它们。
ByteBuffer.allocateDirect()
GetDirectBufferAddress()
kyvafyod4#
以上所有问题,都有一个很好的解决方案(点击下面的链接):getdirectbufferaddress地址如果您有一个对象而不是基元数组,您可以找到如何提供直接访问。
4条答案
按热度按时间szqfcxe21#
当然,使用jni是可能的。
值得参考以下链接:http://journals.ecs.soton.ac.uk/java/tutorial/native1.1/implementing/array.html 总之-
bvk5enib2#
我终于找到了答案。一般来说,用jni做我想做的事情是不可能的。但是,有些虚拟机提供了所需的功能,我使用了jikesrvm:
1) 本机代码需要数组的内存位置。这可以通过使用jikesrvm中的“magic”工具来实现,它提供了一个objectreference和一个address类,允许为每个对象获取一个内存地址。然后,这个地址可以作为long/int参数(使用jni)转发到本机代码,并在那里强制转换到指针。
2) gc不能移动对象。这有点棘手,因为它需要在gc中支持固定。在jikesrvm的情况下,可以用@nonmoving和@nonmovingallocation(也是“magic”的一部分)对对象进行注解。此外,大于8kb的对象(即数组)被放置在一个大的对象空间中,这样就不会移动对象。
qlfbtfca3#
如果您使用的是较新版本的java,请使用bytebuffer对象。
呼叫
ByteBuffer.allocateDirect()
分配缓冲区。直接缓冲区位于垃圾收集器的域之外。要从jni访问缓冲区,请调用GetDirectBufferAddress()
. 它返回一个指向字节缓冲区的指针。这不能在引擎盖下复制。对缓冲区的更改将在java和本机端看到。javadocs对使用直接缓冲区有一些警告:
可以通过调用此类的allocatedirect工厂方法来创建直接字节缓冲区。此方法返回的缓冲区通常比非直接缓冲区具有更高的分配和释放成本。直接缓冲区的内容可能位于正常垃圾收集堆之外,因此它们对应用程序内存占用的影响可能并不明显。因此,建议将直接缓冲区主要分配给受底层系统本机i/o操作影响的大型长寿命缓冲区。一般来说,只有当直接缓冲区在程序性能上产生可测量的增益时,才最好分配它们。
kyvafyod4#
以上所有问题,都有一个很好的解决方案(点击下面的链接):
getdirectbufferaddress地址
如果您有一个对象而不是基元数组,您可以找到如何提供直接访问。