fastFFI 是一个现代高效的 FFI 框架,其开发初衷是提高不同语言之间相互通信的易用性与性能,目前的实现主要是针对 Java 访问 C++ 代码和数据。不同程序设计语言擅长解决不同的问题,因此跨语言调用的需求在现代软件开发过程中越来越强烈。
JNI (Java Native Interface) 是 JVM 标准的 FFI 接口,开发 JNI 应用耗时且易错,除此之外, 频繁的通过 Java Native 方法对 JNI 函数的调用往往会 带来严重的性能问题 。为了使用一个外部的函数,开发者需要首先在 Java 里声明一个 Native 方法,之后再在 Native 端开发一个 JNI 函数,在这个 JNI 函数里实现对外部函数的调用。由于 Java 和 Native 端的类型不同,JNI 函数还需要做相应的类型转换。
相比对普通的 Java 方法的调用,对 Java Native 方法的调用有额外性能开销,这些开销主要来自两部分:
1、对 Java Native 方法以及 JNI 函数调用的传参、上下文切换的开销 ,这是由于 JIT 编译器无法通过内联优化消除对 JNI 函数的调用。这一类开销主要是由于 Java 方法是由 JIT 编译,而 JNI 函数是由 C++ 编译器编译,不同编译器之间存在屏障。
2、Java Native 方法和 JNI 函数之间参数和返回值类型转换 ,例如所有的 Java String 对象需要通过 JNI 提供的接口函数转成对应的 C-style 字符串。这一类开销主要是由于 Java 和 Native 数据类型的不同造成的。
既有的 Java 的 FFI 框架大多称之为抽象 FFI 框架,是基于 JNI 之上提供一些类型支持,主要尝试解决 FFI 的易用性差的问题。事实上,既有的一些流行工具,例如 JNA (Java Native Access) 以及 JNR (Java Native Runtime) ,实现上基于通用 JNI stub 和 dlsym,以牺牲性能来追求极致的易用性。