Java Native Access

Java Native Access (JNA) 是一个由社区开发的库，它使Java程序无需使用Java Native Interface即可轻松访问本地共享库。JNA的设计旨在以最少的努力以原生的方式提供本地访问，且不需要样板代码或胶水代码。

结构 
JNA库使用一个称为外部函数接口库（）的小型本机库来动态调用本机代码。JNA库使用本地函数，允许代码按名称加载库并检索指向该库中函数的指针，使用libffi库来调用它，而无需静态绑定，头文件或任何编译。开发人员使用Java interface描述目标本机库中的函数和结构（struct）。这使得利用平台功能非常容易，而避免了配置或构建JNI的高开销。

JNA支持在macOS，Microsoft Windows，FreeBSD / OpenBSD，Solaris，GNU/Linux，AIX，Windows Mobile和Android上构建和测试。经过适当调整和重编译，可以使其在大多数能够运行Java的平台上运行。

类型对应
这个表格显示了JNA所支持的类型与java类型，Windows通用类型的对应关系.

注意：根据一些预处理器指令和不同的实现，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被用于下列项目中：
 Armed Bear Common Lisp, 使用JNA实现CFFI。
 JRuby,使用JNA实现 POSIX 相关功能。
 Freedom for Media in Java (FMJ)。
JetBrains的IntelliJ IDEA。
 OpenSearchServer,一个开源搜索引擎。
SVNKit, 一个纯Java的Java Subversion client库 ，通过JNA实现相关功能。
VLC media player, 在vlcj库中使用。
 Cyberduck 适用于FTP, SFTP, WebDAV, Cloud Files & Amazon S3的浏览器。
 Log4j,附加日志库。
 Hudson 和· Jenkins，持续集成服务器。
 Webdriver。
 YAJSW (Yet Another Java Service Wrapper)。
 Cassandra, 来自 Apache Software Foundation 的开源分布数据库，使用JNA。

另见
 P/Invoke
 SWIG

参考链接

外部链接
 Java Native Access Web Page 
 Java Native Access - Download page 
 Java Native Access - User Mailing List 
 Java Native Access:An easier way to access native code  by Jeff Friesen, JavaWorld.com,2008-02-05
 Protect Your Legacy Code Investment with JNA by Stephen B. Morris, Java.net,2009-05-20

 JNA is now a Githubber by Daniel Doubrovkine, 2011-09-20
 Calling the Lotus Domino C-API with JNA  by Jesper Kiaer 2010-03-21

Java