原作者 | Todd Fast, Timothy Wall, Liang Chen |
---|---|
首次发布 | 2007年5月9日 |
当前版本 | 5.5.0(2019年7月19日[1]) |
源代码库 | |
编程语言 | C 和 Java |
操作系统 | Windows, macOS, Android, AIX, FreeBSD, GNU/Linux, OpenBSD, Solaris, Windows Mobile |
平台 | Java 1.4 或更高 (只能使用JNA 3.5.2前的版本), Java 1.6 (JNA 4.0.0 以上) |
文件大小 | 1.83 MB (存档后) |
类型 | 库 |
许可协议 | LGPL version 2.1,JNA 4.0后增加了 Apache Software License, version 2.0 |
网站 | github |
Java Native Access (JNA) 是一个由社区开发的库,它使Java程序无需使用Java Native Interface即可轻松访问本地共享库。JNA的设计旨在以最少的努力以原生的方式提供本地访问,且不需要样板代码或胶水代码。
JNA库使用一个称为外部函数接口库(libffi)的小型本机库来动态调用本机代码。JNA库使用本地函数,允许代码按名称加载库并检索指向该库中函数的指针,使用libffi库来调用它,而无需静态绑定,头文件或任何编译。开发人员使用Java interface描述目标本机库中的函数和结构(struct)。这使得利用平台功能非常容易,而避免了配置或构建JNI的高开销。
JNA支持在macOS,Microsoft Windows,FreeBSD / OpenBSD,Solaris,GNU/Linux,AIX,Windows Mobile和Android上构建和测试。经过适当调整和重编译,可以使其在大多数能够运行Java的平台上运行。
这个表格显示了JNA所支持的类型与java类型,Windows通用类型的对应关系.[2]
C类型 | 大小 | Java类型 | Windows通用类型 |
---|---|---|---|
char | 8-bit integer | byte | BYTE, TCHAR |
short | 16-bit | short | short WORD |
wchar_t | 16/32-bit character | char | WCHAR, TCHAR |
int | 32-bit integer | int | DWORD |
int | boolean value | boolean | BOOL |
long | 32/64-bit integer | NativeLong | LONG |
long long, __int64 | 64-bit integer | long | LONGLONG |
float | 32-bit FP | float | |
double | 64-bit FP | double | |
char* | C string | String | LPCTSTR |
void* | pointer | Pointer | LPVOID, HANDLE, LPXXX |
注意:根据一些预处理器指令和不同的实现,TCHAR可能为char或wchar_t。LPCTSTR也是一样的。
JNA没有规定内存字节的对齐方式。JNA默认为遵循OS平台的设置,但也可以自定义对齐方式。如果本机库的文档中未提供关于内存对齐的详细信息,则必须通过反复试验确定正确的对齐方式。
下面这个例子展示了JNA如何加载C标准库并使用其中的printf函数。
注意: 这个例子是跨平台的,这意味着它可以在 Windows / GNU+Linux / Unix / macOS 运行,并得到完全相同的结果。
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Platform;
/** 这个例子展示了JNA的一个用法 */
public class HelloWorld {
public interface CLibrary extends Library {
CLibrary INSTANCE = (CLibrary) Native.loadLibrary(
(Platform.isWindows() ? "msvcrt" : "c"), CLibrary.class);
void printf(String format, Object... args);
}
public static void main(String[] args) {
CLibrary.INSTANCE.printf("Hello, World\n");
for (int i = 0; i < args.length; i++) {
CLibrary.INSTANCE.printf("Argument %d: %s\n", i, args[i]);
}
}
}
下面这个例子使用了C POSIX库并调用其中的mkdir函数。
注意: 这个例子在POSIX兼容的系统中是跨平台的,这意味着它可以在所有POSIX兼容系统中运行并获得相同结果,但它无法在大多数Windows系统上运行。
import com.sun.jna.Library;
import com.sun.jna.Native;
/** Simple example of native C POSIX library declaration and usage. */
public class ExampleOfPOSIX {
public interface POSIX extends Library {
public int chmod(String filename, int mode);
public int chown(String filename, int user, int group);
public int rename(String oldpath, String newpath);
public int kill(int pid, int signal);
public int link(String oldpath, String newpath);
public int mkdir(String path, int mode);
public int rmdir(String path);
}
public static void main(String[] args) {
POSIX posix = (POSIX) Native.loadLibrary("c", POSIX.class);
posix.mkdir("/tmp/newdir", 0777);
posix.rename("/tmp/newdir","/tmp/renamedir");
}
}
下面这个例子加载了Kernel32.dll并调用了其中的Beep和Sleep函数。
注意: 这个例子只能在Windows下运行。
import com.sun.jna.Library;
import com.sun.jna.Native;
/** 这是JNA调用Windows dll的一个例子 */
public class BeepExample {
public interface Kernel32 extends Library {
// FREQUENCY可以为 37 和 32767间任意一整数
// DURATION 的单位为毫秒
public boolean Beep(int FREQUENCY, int DURATION);
public void Sleep(int DURATION);
}
public static void main(String[] args) {
Kernel32 lib = (Kernel32) Native.loadLibrary("kernel32", Kernel32.class);
lib.Beep(698, 500);
lib.Sleep(500);
lib.Beep(698, 500);
}
}
JNA被用于下列项目中: