我们知道在native代码中有很多指针,而这些指针在JNA中都映射为Pointer。除了Pointer,JNA还提供了一个更强大的Memory类。本文将讨论JNA中Pointer和Memory的使用。PointerPointer是JNA中引入的一个类,用于表示native方法中的指针。我们回想一下native方法中的指针是什么?native方法中的指针其实就是一个地址,这个地址就是真正对象的内存地址。所以在Pointer中定义了一个peer属性,用来存放真实对象的内存地址:protectedlongpeer;实际上,Pointer的构造函数需要传入这个peer参数:publicPointer(longpeer){this.peer=peer;接下来,让我们看看如何从Pointer中获取一个真实的对象。这里我们以字节数组为例:}其实这个方法调用的是Native.read方法,我们继续看这个read方法:staticnativevoidread(Pointerpointer,longbaseaddr,longoffset,byte[]buf,intindex,intlength);你可以看到它是一个真正的读取指针对象的本地方法。除了Byte数组,Pointer还提供了很多其他类型的读取方法。读和写,看看Pointer是怎么写数据的:}同样调用Native.write方法写入数据。这里的Native.write方法也是一个native方法:staticnativevoidwrite(Pointerpointer,longbaseaddr,longoffset,byte[]buf,intindex,intlength);指针还提供了许多其他类型的数据写入方法。当然还有更直接的get*方法:publicbytegetByte(longoffset){returnNative.getByte(this,this.peer,offset);}特殊指针:Opaque在Pointer中,有两个createConstant方法,使用来创建一个不可读不可写的Pointer:publicstaticfinalPointercreateConstant(longpeer){returnnewOpaque(peer);}publicstaticfinalPointercreateConstant(intpeer){returnnewOpaque((long)peer&0xFFFFFFFF);}实际上返回的是Opaque类,它继承自Pointer,但是里面所有的读写方法都会抛出UnsupportedOperationException:}@OverridepublicPointershare(longoffset,longsize){thrownewUnsupportedOperationException(MSG);}MemoryPointer是一个基本的指针映射,如果对于使用nativemalloc方法分配的内存空间,除了Pointer指针的起始位置之外,我们还需要知道分配空间的大小。所以一个简单的指针是不够的。在这种情况下,我们需要使用内存。内存是一种特殊的指针,它保存分配的空间大小。我们来看看Memory的定义以及它包含的属性:publicclassMemoryextendsPointer{...私有静态LinkedReference头;//用于实例跟踪的双向链表的头部privatestaticfinalWeakMemoryHolderbuffers=newWeakMemoryHolder();私人最终LinkedReference参考;//用于跟踪实例保护的长尺寸;//sizeofthemalloc'edspace...}DefinedinMemory收集了5条数据,我们将一一介绍。首先是最重要的size,size表示Memory中内存空间的大小,我们看一下Memory的构造函数:publicMemory(longsize){this.size=size;if(size<=0){thrownewIllegalArgumentException("分配大小必须大于零");}peer=malloc(size);if(peer==0)thrownewOutOfMemoryError("Cannotallocate"+size+"bytes");reference=LinkedReference.track(这个);可以看到Memory类型的数据需要传入一个size参数,表示Memory占用的空间大小。当然这个size必须大于0。然后调用native方法的malloc方法分配一块内存空间,返回的peer保存内存空间的起始地址。如果peer==0,表示分配失败。如果分配成功,将当前Memory保存到LinkedReference中,用于跟踪当前位置。我们可以看到Memory中有两个LinkedReferences,一个是HEAD,一个是reference。LinkedReference本身是一个WeakReference,weekReference引用的对象只要进行垃圾回收就会被回收,不管内存是否不足。privatestaticclassLinkedReferenceextendsWeakReference
