我想在本机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
作为缓冲区大小吗? (当然,我提供的是我不尝试从缓冲区读取)
答案 0 :(得分:1)
JVM可以自由管理ByteBuffer对象,但它始终包含相同的地址和容量。它不会对ByteBuffer指向的内存做任何事情,除非你在它上面调用ByteBuffer方法并且它永远不会移动它。
但是因为你不打算调用ByteBuffer方法,所以ByteBuffer和jlong是等价的。在我看来,使用jlong会更清楚,即使你必须在JNI函数中强制转换。毕竟,在Java方面,您正在创建和存储句柄,而在JNI方面,您将句柄视为指针。演员表明了这一点。
答案 1 :(得分:0)
意思是,java会对我的指针做有趣的事情,比如可能重新定位它或者垃圾收集它吗?
指针只是一个32位数字。如果你不改变它,JVM就不会。
JVM“知道”引用所在的唯一原因是它们显示为类的字段。这不是字段,也不是存储在引用中。
其次,如果我事先不知道World的大小(它是向前声明的),那么将0作为缓冲区大小是否可以?
不,ByteBuffer是一个固定的大小,你不能超过它。当你知道它应该有多大时,我会设置ByteBuffer。
我不清楚你要做什么,但我怀疑有更好的方法。