Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/397.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/59.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
是否允许本机代码直接访问java堆中的对象?_Java_C_Java Native Interface_Jna_Native Code - Fatal编程技术网

是否允许本机代码直接访问java堆中的对象?

是否允许本机代码直接访问java堆中的对象?,java,c,java-native-interface,jna,native-code,Java,C,Java Native Interface,Jna,Native Code,我在Java中有一个对象数组,我想允许本机C代码直接访问该数组(没有复制或访问函数)。这可能吗?我不介意解决方案是否是特定于JVM的。当然,使用JNI是可能的 值得参考此链接: 简言之— #include <jni.h> #include "IntArray.h" JNIEXPORT jint JNICALL Java_IntArray_sumArray(JNIEnv *env, jobject obj, jintArray arr) { jsize len = (*env)

我在Java中有一个对象数组,我想允许本机C代码直接访问该数组(没有复制或访问函数)。这可能吗?我不介意解决方案是否是特定于JVM的。

当然,使用JNI是可能的

值得参考此链接: 简言之—

#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;
}
#包括
#包括“IntArray.h”
JNIEXPORT jint JNICALL
Java_IntArray_sumArray(JNIEnv*env、jobject obj、jintArray arr)
{
jsize len=(*env)->GetArrayLength(env,arr);
int i,和=0;
jint*body=(*env)->GetIntArrayElements(env,arr,0);
对于(i=0;iReleaseIntarayElements(环境、arr、主体,0);
回报金额;
}

当然,使用JNI是可能的

值得参考此链接: 简言之—

#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;
}
#包括
#包括“IntArray.h”
JNIEXPORT jint JNICALL
Java_IntArray_sumArray(JNIEnv*env、jobject obj、jintArray arr)
{
jsize len=(*env)->GetArrayLength(env,arr);
int i,和=0;
jint*body=(*env)->GetIntArrayElements(env,arr,0);
对于(i=0;iReleaseIntarayElements(环境、arr、主体,0);
回报金额;
}

如果您使用的是较新版本的java,请使用对象

调用
ByteBuffer.allocateDirect()
来分配缓冲区。直接缓冲区位于垃圾收集器的域之外。要从JNI访问缓冲区,请调用。它返回一个指向字节缓冲区的指针。这不会在后台进行复制。对缓冲区的更改将在Java和本机端看到

javadocs对使用直接缓冲区有一些警告:

可以通过调用此类的allocateDirect工厂方法来创建直接字节缓冲区。此方法返回的缓冲区通常比非直接缓冲区具有更高的分配和释放成本。直接缓冲区的内容可能位于正常垃圾收集堆之外,因此其对内存的影响也是如此应用程序的占用空间可能不明显。因此,建议直接缓冲区主要分配给受底层系统本机I/O操作影响的大型、长寿命的缓冲区。一般来说,最好仅在直接缓冲区在程序性能方面产生可测量的增益时才分配


如果您使用的是较新版本的java,请使用对象

调用
ByteBuffer.allocateDirect()
来分配缓冲区。直接缓冲区位于垃圾收集器的域之外。要从JNI访问缓冲区,请调用。它返回一个指向字节缓冲区的指针。这不会在后台进行复制。对缓冲区的更改将在Java和本机端看到

javadocs对使用直接缓冲区有一些警告:

可以通过调用此类的allocateDirect工厂方法来创建直接字节缓冲区。此方法返回的缓冲区通常比非直接缓冲区具有更高的分配和释放成本。直接缓冲区的内容可能位于正常垃圾收集堆之外,因此其对内存的影响也是如此应用程序的占用空间可能不明显。因此,建议直接缓冲区主要分配给受底层系统本机I/O操作影响的大型、长寿命的缓冲区。一般来说,最好仅在直接缓冲区在程序性能方面产生可测量的增益时才分配


我终于找到了答案。一般来说,用JNI做我想做的事情是不可能的。但是,有些虚拟机提供了所需的功能,我使用了JikesRVM:

1) 本机代码需要数组的内存位置。这可以使用JikesRVM中的“Magic”功能实现,它提供了一个ObjectReference和一个Address类,允许获取每个对象的内存地址。然后可以将该地址作为long/int参数转发给本机代码(使用JNI)有一个指针


2) GC不能四处移动对象。这有点棘手,因为它需要在GC中支持固定。对于JikesRVM,对象可以用@NonMoving和@NonMovingAllocation(也是“Magic”的一部分)进行注释。此外,大于8KB的对象(即数组)被放置在一个大的对象空间中,这样就不会移动对象。

我终于找到了答案。一般来说,用JNI做我想做的事情是不可能的。但是,有些虚拟机提供了所需的功能,我使用了JikesRVM:

1) 本机代码需要数组的内存位置。这可以使用JikesRVM中的“Magic”功能实现,它提供了一个ObjectReference和一个Address类,允许为每个对象获取内存地址。然后,该地址可以作为long/int参数(使用JNI)转发到本机代码,并在那里转换为指针


2) GC不能四处移动对象。这有点棘手,因为它需要在GC中支持固定。对于JikesRVM,对象可以用@NonMoving和@NonMovingAllocation(也是“Magic”的一部分)进行注释。此外,大于8KB的对象(即数组)被放置在一个大的对象空间中,这样就不会移动对象。

以上所有问题都有一个很好的解决方案(单击下面的链接):


如果您有一个对象而不是原始数组,您可以找到如何提供直接访问。

以上所有问题都有一个很好的解决方案(单击下面的链接):


如果你有一个对象而不是原始数组,你可以找到如何提供直接访问。

当GC移动对象时,你想做什么?@SLaks:如果VM提供了这种能力,那么我认为它不会在JNI代码具有访问权限的期间重新定位数组数据。IIRC您基本上需要每个数组有一个引用计数才能实现“现在不要重新定位”。@SteveJessop-您知道实践中有哪个主流JVM会这样做吗?我认为这将给GC带来巨大的性能成本。首先,复制收集算法是有问题的。@Steph