- バックアップ一覧
- 差分 を表示
- 現在との差分 を表示
- ソース を表示
- Java/JNI/ネイティブコードの実行手順 へ行く。
- 1 (2020-04-19 (日) 21:03:46)
- 2 (2020-04-19 (日) 23:00:12)
- 3 (2020-04-20 (月) 04:40:54)
- 4 (2020-04-23 (木) 08:08:59)
JNI †
JNIは、Java Native Interfaceの略であり、JavaからC/C++のネイティブコードを実行するための仕様と技術である。
既存のネイティブで実行するプログラム資産やJavaで対応できないプラットフォーム固有の機能を利用するには、JNIやJava Native Access (JNA) がある。
ネイティブコード実行の手順 †
- ネイティブコードの特定
- ネイティブコードのインタフェースを定義
- Javaコードの作成
- Javaコードをjavacでコンパイル
- javahでヘッダファイルを生成
- ネイティブコードをコンパイルし共有ライブラリを作成
サンプルで手順を見ていく。
サンプルで使用するディレクトリ構造は以下の通り。
~/workspace/java/jni/jnisample $ tree . . ├── Makefile ├── hello.c └── src └── main └── java └── sample └── JNISample.java 4 directories, 3 files
- パッケージsampleにJavaプログラムを配置する。
- hello.cにネイティブコードを書き、JNISample.javaからhello.cの関数を呼び出す。
Makefileはビルドと実行の簡単化のために作成する。
ネイティブコードのインタフェースを定義 †
今回のサンプルで使用するネイティブコードは以下。
#include "JNISample.h" JNIEXPORT void JNICALL Java_sample_JNISample_hello (JNIEnv *env, jobject obj, jstring jmsg) { jboolean isCopy; const char *msg = (*env)->GetStringUTFChars(env, jmsg, &isCopy); if (msg == NULL) return; printf("Hello, %s\n", msg); (*env)->ReleaseStringUTFChars(env, jmsg, msg); }
Javaコードの作成 †
Javaプログラムでは、ネイティブコード呼び出しのメソッドはnativeキーワードで指定する。
JNISampleに引数を与えて実行すると、標準出力にメッセージを表示するだけの簡単なサンプルとする。
package sample; class JNISample { static { System.loadLibrary("jnisample"); } // C側のプログラムを呼び出すインターフェース public native void hello(String message); public static void main(String[] args) { JNISample hello = new JNISample(); hello.hello(args[1]); } }
Javaコードをjavacでコンパイル †
作成したJavaプログラムをコンパイルする。通常通りのjavacコマンドによるコンパイルである。
以下では、classesの下にclassファイルを出力している。
mkdir -p classes javac -d classes src/main/java/sample/JNISample.java
javahでヘッダファイルを生成 †
javahコマンドで、ネイティブコードでインクルードするヘッダファイルを生成する。
このヘッダファイルは、jni.hのヘッダファイルをインクルードしているので、hello.c内でJNIインタフェースを使用できる。
javah -o JNISample.h -classpath classes sample.JNISample
デフォルトだと、sample_JNISample.h
のようなヘッダファイル名となる。
パッケージ名が長いとファイル名が長くなってしまうこと、ファイル名を固定化したい、の理由で上記では-o
オプションで生成されるファイル名を指定する。
生成されたヘッダファイルは以下のようになる。
このファイルは自動生成されるため基本的には修正しない。
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class sample_JNISample */ #ifndef _Included_sample_JNISample #define _Included_sample_JNISample #ifdef __cplusplus extern "C" { #endif /* * Class: sample_JNISample * Method: hello * Signature: (Ljava/lang/String;)V */ JNIEXPORT void JNICALL Java_sample_JNISample_hello (JNIEnv *, jobject, jstring); #ifdef __cplusplus } #endif #endif
JNIで自動生成されるメソッドの引数には、JNIEnvとjobject(staticの場合は、jclass)が渡される。
jobjectはオブジェクト、jclassはクラスの参照である。
その後にメソッドの引数定義が続く。
ネイティブコードをコンパイルし共有ライブラリを作成 †
ネイティブコードをビルドして、共有ライブラリを作成する。
以下はmacOS上でビルドしている。各プラットフォームの仕様を参照されたい。
gcc -O2 -Wall -I$(/usr/libexec/java_home)/include{,/darwin} -shared -o libjnisample.jnilib hello.c
以上でライブラリを作成できたので実際に実行してみる。
$ java -classpath classes sample.JNISample tarou
Hello, tarou
メッセージを表示することができている。
サンプル Makefile
Makefile及びサンプルプログラムを添付しておく。
JAVA_HOME := $(shell /usr/libexec/java_home) CC = gcc CFLAGS = -O2 -Wall $(addprefix -I$(JAVA_HOME)/,include include/darwin) SOURCES = hello.c OBJS = $(SOURCES:%.c=%.o) PROGRAM = libjnisample.jnilib CLASSES = src/main/java/sample/JNISample.java .SUFFIXES: .java .class .PHONY: all all: $(PROGRAM) $(PROGRAM): JNISample.h $(OBJS) $(CC) $(CFLAGS) -shared $(OBJS) -o $@ JNISample.h: classes javah -o JNISample.h -classpath classes sample.JNISample .PHONY: classes classes: $(CLASSES:.java=.class) .java.class: mkdir -p classes javac -d classes $< .PHONY: run run: java -classpath classes -Djava.library.path=. sample.JNISample $(ARGS) .PHONY: clean clean: $(RM) -rf *.o *.jnilib classes JNISample.h
ビルドと実行方法は以下の通りである。
$ make $ make ARGS="tarou" run
サンプル JNIサンプルプログラム jnisample.tar.gz
参考リンク †
- Java Native Interface仕様の目次 - on https://docs.oracle.com/javase/jp/8/docs/technotes/guides/jni/spec/jniTOC.html
- NI:Java Native Interfaceプログラミング―C/C++コードを用いたJavaアプリケーション開発 (Java books) -- on https://www.amazon.co.jp/dp/4894710803
- JNI Example (Mac OS) - on https://gist.github.com/DmitrySoshnikov/8b1599a5197b5469c8cc07025f600fdb
- eginning Java 8 APIs, Extensions and Libraries: Swing, JavaFX, JavaScript, JDBC and Network Programming APIs (Expert's Voice in Java) - on https://www.amazon.co.jp/dp/1430266619/