Java Native Access
Java Native Access (JNA) 是一個由社區開發的庫,它使Java程式無需使用Java Native Interface即可輕鬆訪問本地共用庫。JNA的設計旨在以最少的努力以原生的方式提供本地訪問,且不需要樣板代碼或膠水代碼。
原作者 | 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 |
結構
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被用於下列專案中:
- Armed Bear Common Lisp, 使用JNA實現CFFI。[3]
- JRuby,使用JNA實現 POSIX 相關功能。[4][5]
- Freedom for Media in Java (FMJ)。[6]
- JetBrains的IntelliJ IDEA。
- OpenSearchServer,一個開源搜尋引擎。
- SVNKit, 一個純Java的Java Subversion client庫 ,通過JNA實現相關功能。
- VLC media player, 在vlcj庫中使用。[7]
- Cyberduck 適用於FTP, SFTP, WebDAV, Cloud Files & Amazon S3的瀏覽器。
- Log4j,附加紀錄檔庫。[8]
- Hudson 和· Jenkins,持續整合伺服器。
- Webdriver。
- YAJSW (Yet Another Java Service Wrapper)。
- Cassandra, 來自 Apache Software Foundation 的開源分佈資料庫,使用JNA。[9]
另見
參考連結
- ^ Release 5.5.0. Groups.google.com. 2019-10-30 [2020-07-23]. (原始內容存檔於2011-01-22).
- ^ Default Type Mappings. jna.dev.java.net. [2011-08-02]. (原始內容存檔於2014-06-01).
- ^ asdf/cffi – armedbear. Abcl.org. [2018-12-07]. (原始內容存檔於2020-07-17).
- ^ Nutter, Charles Oliver. Java Native Access + JRuby = True POSIX. 2007-09-02 [2018-12-07]. (原始內容存檔於2020-11-09).
- ^ JNA brings native code to JRuby. infoq.com. 2007-09-05 [2010-05-22]. (原始內容存檔於2020-10-26).
- ^ Home - FMJ. Fmj-sf.net. [2018-12-07]. (原始內容存檔於2020-11-23).
- ^ vlcj. Capricasoftware.co.uk. Caprica Software Limited. [2018-10-23]. (原始內容存檔於2020-11-01).
- ^ dblock/log4jna. GitHub. [2018-10-23]. (原始內容存檔於2020-09-17) (英語).
- ^ apache/cassandra. GitHub. [2018-12-07]. (原始內容存檔於2020-12-10).
外部連結
- 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
- Dasgupta, Sanjay. Simplify Native Code Access with JNA. Java.net. 2009-09-11 [2020-07-23]. (原始內容存檔於2009-11-15).
- 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