2013-05-09 37 views
6

或者我必须有一个调用env-> NewDirectByteBuffer(buffer,size)的JNI助手函数吗?有没有一种方法可以仅通过Java中的指针创建直接的ByteBuffer?

+1

你看着sun.misc.unsafe?它允许你直接与内存交互。 – assylias 2013-05-09 15:42:18

+0

我看了一下,没有看到用sun.misc.unsafe创建直接字节缓冲区的方法。我确实找到了一种创建DirectByteBuffer的方式,它是通过反射来实现的。使用java.lang.Class.getDeclaredConstructor创建一个Constructor对象,setAccessable为true并用适当的参数调用newInstance。虽然没有什么JNI代码,但是你不必写任何jijy代码。 – 2013-05-12 20:39:46

回答

15

我所做的是创建一个正常的DirectByteBuffer并更改它的地址。

Field address = Buffer.class.getDeclaredField("address"); 
address.setAccessible(true); 
Field capacity = Buffer.class.getDeclaredField("capacity"); 
capacity.setAccessible(true); 

ByteBuffer bb = ByteBuffer.allocateDirect(0).order(ByteOrder.nativeOrder()); 
address.setLong(bb, addressYouWantToSet); 
capacity.setInt(bb, theSizeOf); 

从这一点开始,您可以访问引用基础地址的ByteBuffer。我已经做到了这一点,以访问网络适配器上的内存零拷贝,它工作正常。

您可以直接为您的地址创建一个DirectByteBuffer,但这比较模糊。


另一种方法是(OpenJDK的/热点的JVM和本地字节顺序这只作品)使用不安全

Unsafe.getByte(address); 
Unsafe.getShort(address); 
Unsafe.getInt(address); 
Unsafe.getLong(address); 
+0

很好的答案,但是我不得不对它进行一些操作,特别是Field address = Buffer.class.getDeclaredField(“address”)。 – Erik 2016-08-23 15:50:17

+0

@Erik谢谢你的纠正。 – 2016-08-23 22:19:17

+0

所以这里是对原始问题的跟进,因为你还在关注。以这种方式清理连接到ByteBuffer的内存的最佳方法是什么? ByteBuffer会完成免费地址还是应该调用者干预并清理分配?为了这个问题的目的,假设我已经写了一个带有malloc和免费的包装器的JNI库。现在我可能更应该考虑它自己的问题了。 – Erik 2016-08-23 22:23:58

相关问题