可以安全地将指针存储在JNI直接bytebuffer中吗?

时间:2013-05-10 05:10:08

标签: java android-ndk java-native-interface native

我想在本机c ++对象周围创建一个java对象包装器。我这样做是通过将指向c ++对象的指针放在直接的ByteBuffer中,如下所示:

java方面:

public class World {
  private final ByteBuffer pointer;
  public World() {
    pointer = init();
  }

  private native ByteBuffer init();
  public native void destroy();
}

原生方:

extern "C" jobject Java_blabla_World_init(JNIEnv *e, jobject self) {
  return env->NewDirectByteBuffer(new World, sizeof(World));
}

安全吗?意思是,java会对我的指针做有趣的事情,比如可能重新定位它或者垃圾收集它吗?

其次,如果我事先不知道World的大小(它是前向声明的),那么只能将0作为缓冲区大小吗? (当然,我提供的是我不尝试从缓冲区读取)

2 个答案:

答案 0 :(得分:1)

JVM可以自由管理ByteBuffer对象,但它始终包含相同的地址和容量。它不会对ByteBuffer指向的内存做任何事情,除非你在它上面调用ByteBuffer方法并且它永远不会移动它。

但是因为你不打算调用ByteBuffer方法,所以ByteBuffer和jlong​​是等价的。在我看来,使用jlong​​会更清楚,即使你必须在JNI函数中强制转换。毕竟,在Java方面,您正在创建和存储句柄,而在JNI方面,您将句柄视为指针。演员表明了这一点。

答案 1 :(得分:0)

  

意思是,java会对我的指针做有趣的事情,比如可能重新定位它或者垃圾收集它吗?

指针只是一个32位数字。如果你不改变它,JVM就不会。

JVM“知道”引用所在的唯一原因是它们显示为类的字段。这不是字段,也不是存储在引用中。

  

其次,如果我事先不知道World的大小(它是向前声明的),那么将0作为缓冲区大小是否可以?

不,ByteBuffer是一个固定的大小,你不能超过它。当你知道它应该有多大时,我会设置ByteBuffer。

我不清楚你要做什么,但我怀疑有更好的方法。