Java Native Access (JNA) とは、JavaプログラムがJava Native Interfaceを用いずにネイティブの共有ライブラリにアクセスする方法を提供するライブラリである。JNA は最小限の作業でネイティブコードにアクセスできることを目指して設計されており、決まりきったアクセスコードを書いたりグルーコードの生成を行ったりせず、ネイティブコードへ正しく簡単にアクセスすることを最優先としている(ただし、性能にも注意が払われている)。JNAライブラリはネイティブコードを呼び出すためにlibffiを用いており、名前を指定してライブラリをロードするネイティブの関数を用いて、目的のライブラリ関数の関数ポインタを取得する。ネイティブコードにアクセスする過程で静的なバインディング、ヘッダファイル、またコンパイルは必要ない。アプリケーションの開発者はJavaのインターフェイスを用いて対象のネイティブライブラリの関数や構造体を記述する。これによって、JNIコードを記述しビルドする大きな労力をかけずにきわめて簡単にネイティブプラットフォームの機能を利用することができる。
JNAの採用例
型の割り当て
JNAライブラリがサポートするJavaとネイティブコードの割り当てを下表に示す[6]。
ネイティブ型
|
サイズ
|
Java 言語の型
|
Windows での一般的な型
|
char
|
8ビット整数
|
byte
|
BYTE, TCHAR
|
short
|
16ビット整数
|
short
|
WORD
|
wchar_t
|
16/32ビット文字
|
char
|
TCHAR
|
int
|
32ビット整数
|
int
|
DWORD
|
int
|
真偽値
|
boolean
|
BOOL
|
long
|
32/64ビット整数
|
NativeLong
|
LONG
|
long long
|
64ビット整数
|
long
|
__int64
|
float
|
32ビット浮動小数点数
|
float
|
|
double
|
64ビット浮動小数点数
|
double
|
|
char*
|
C 文字列
|
String
|
LPCTSTR
|
void*
|
ポインタ
|
Pointer
|
LPVOID, HANDLE, LPXXX
|
例
下記のプログラムはプラットフォームの標準Cライブラリをロードし、printf関数を呼び出す。
注: 以下のコードはWindows、Linux / UNIX / macOSプラットフォームで動作する。
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Platform;
/** Library の宣言と使用法の簡単な例 */
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ライブラリをロードし、標準APImkdirを呼び出す。
注: 下記のコードはPOSIX環境で動作する。
import com.sun.jna.Library;
import com.sun.jna.Native;
/** POSIXライブラリの宣言と使用法の例 */
public class PosixExample {
public interface POSIX extends Library {
POSIX INSTANCE = (POSIX) Native.loadLibrary("c", POSIX.class);
int chmod(String filename, int mode);
int chown(String filename, int user, int group);
int rename(String oldpath, String newpath);
int kill(int pid, int signal);
int link(String oldpath, String newpath);
int mkdir(String path, int mode);
int rmdir(String path);
}
public static void main(String[] args) {
POSIX posix = POSIX.INSTANCE;
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;
/** MS-Windows の Library の宣言と使用法の例 */
public class BeepExample {
public interface Kernel32 extends Library {
Kernel32 INSTANCE = (Kernel32) Native.loadLibrary("kernel32", Kernel32.class);
boolean Beep(int dwFreq, int dwDuration);
void Sleep(int dwMilliseconds);
}
public static void main(String[] args) {
Kernel32 kernel32 = Kernel32.INSTANCE;
kernel32.Beep(698, 500);
kernel32.Sleep(500);
kernel32.Beep(698, 500);
}
}
参考文献
関連項目
外部リンク