9. java高级用法之:JNA中的回调
简介
什么是callback呢?简单点说callback就是回调通知,当我们需要在某个方法完成之后,或者某个事件触发之后,来通知进行某些特定的任务就需要用到callback了。
最有可能看到callback的语言就是javascript了,基本上在javascript中,callback无处不在。为了解决callback导致的回调地狱的问题,ES6中特意引入了promise来解决这个问题。
为了方便和native方法进行交互,JNA中同样提供了Callback用来进行回调。JNA中回调的本质是一个指向native函数的指针,通过这个指针可以调用native函数中的方法,一起来看看吧。
JNA中的Callback
先看下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接口很简单,里面定义了一个interface和两个属性。
先来看这个interface,interface名字叫做UncaughtExceptionHandler,里面有一个uncaughtException方法。这个interface主要用于处理JAVA的callback代码中没有捕获的异常。
注意,在uncaughtException方法中,不能抛出异常,任何从这个方法抛出的异常都会被忽略。
METHOD_NAME这个字段指定了Callback要调用的方法。
如果Callback类中只定义了一个public的方法,那么默认callback方法就是这个方法。如果Callback类中定义了多个public方法,那么会选择METHOD_NAME = "callback"的这个方法作为callback。
最后一个属性就是FORBIDDEN_NAMES。表示在这个列表里面的名字是不能作为callback方法使用的。
目前看来是有三个方法名不能够被使用,分别是:"hashCode", "equals", "toString"。
Callback还有一个同胞兄弟叫做DLLCallback,我们来看下DLLCallback的定义:
public interface DLLCallback extends Callback {
@java.lang.annotation.Native
int DLL_FPTRS = 16;
}
DLLCallback主要是用在Windows API的访问中。
对于callback对象来说,需要我们自行负责对callback对象的释放工作。如果native代码尝试访问一个被回收的callback,那么有可能会导致VM崩溃。
callback的应用
callback的定义
因为JNA中的callback实际上映射的是native中指向函数的指针。首先看一下在struct中定义的函数指针:
struct _functions {
int (*open)(const char*,int);
int (*close)(int);
};
在这个结构体中,定义了两个函数指针,分别带两个参数和一个参数。
对应的JNA的callback定义如下:
public class Functions extends Structure {
public static interface OpenFunc extends Callback {
int invoke(String name, int options);
}
public static interface CloseFunc extends Callback {
int invoke(int fd);
}
public OpenFunc open;
public CloseFunc close;
}