JNA介绍
JNA(Java Native Access )提供一组Java工具类用于在运行期动态访问系统本地库(native library:如Window的dll)而不需要编写任何Native/JNI代码。开发人员只要在一个java接口中描述目标native library的函数与结构,JNA将自动实现Java接口到native function的映射。
windows的dll文件:动态链接库,一个包含可由多个程序同时使用的代码和数据的库。应用程序中加载 DLL 时,可以使用两种链接方法来调用导出的 DLL 函数。 这两种链接方法是加载时动态链接和运行时动态链接。
JNA映射
使用的函数必须与链接库中的函数原型保持一致,这是JNA甚至所有跨平台调用的难点,因为C/C++的类型与Java的类型是不一样的,你必须转换成java对应类型让它们保持一致,这就是类型映射(Type Mappings),JNA官方给出的默认类型映射表如下:
注意:C语言中的char类型的字节占1个字节,但是java中的char是两个字节(16位)
JNA的回调函数
回调函数:在计算机程序设计中,回调函数,或简称回调(Callback 即call then back 被主函数调用运算后会返回主函数),是指通过函数参数传递到其它代码的,某一块可执行代码的引用。这一设计允许了底层代码调用在高层定义的子程序。回调函数分为同步回调和异步回调,同步回调是会等待回调函数执行完成之后才执行其他的业务。异步调用发生在某些业务十分耗时,又需要立即返回结果,这个时候需要开辟新的线程处理耗时业务,业务处理完了,再去回调回调函数,处理其他业务。
JNA 中 Callback 的定义
public interface Callback {
interface UncaughtExceptionHandler {
void uncaughtException(Callback c, Throwable e);
}
String METHOD_NAME = "callback";
List<String> FORBIDDEN_NAMES = Collections.unmodifiableList(
Arrays.asList("hashCode", "equals", "toString"));
}
所有的 Callback 方法都需要实现这个 Callback 接口。
Callback 还有一个同胞兄弟叫做 DLLCallback,我们来看下 DLLCallback 的定义:
public interface DLLCallback extends Callback {
@java.lang.annotation.Native
int DLL_FPTRS = 16;
}
DLLCallback 主要是用在 Windows API 的访问中。
对于 callback 对象来说,需要我们自行负责对 callback 对象的释放工作。如果 native 代码尝试访问一个被回收的 callback,那么有可能会导致 VM 崩溃。