Java

JavaでJNIを使ってみる

ふと、Java からネイティブコードの呼び出し方法を調べてみました。

今回はネイティブコードとして、Windows の DLL、Linux の so、Mac の jnilib を Call する方法を調査してみます。

Java には標準で JNI(Java Native Interface)という機能があり、Java で開発されたプログラムから他の言語で開発されたネイティブコードを利用するための API として利用できます。

開発環境は以下の通りで、dll は Windows じゃないですが Cygwin 上で作成することにしました。

boland の C++ はユーザー登録が面倒なのでやめました。

Eclipse3.2.0(ビルドはAntを使用)
jdk1.5.0_13
Cygwin(gcc)
Linux(gcc)
MacOS(gcc)

Javaプログラムの作成

まずは、ネイティブメソッドを含む Java プログラムを作成してコンパイルします。

今回は Ant で定義しましたが、コマンドラインでビルドするときは下記のようにします。

次に、生成されたクラスファイルからヘッダファイルを作成します。

こちらも、コマンドラインでの生成方法を書いておきます。

上記で生成したヘッダファイルを参照して C++ のプログラムを作成します。

今回は、クラス名が sample、Java のネイティブメソッドを getWord とします。

最後に、作成した C++ プログラムから共有ライブラリを作成します。

so や jnilib ファイルは、ファイル名の先頭に lib を付けます。

次は Java や C++ のソースも交えて、それぞれのプラットフォームでのライブラリの作成方法をまとめたいと思います。

Cygwin, Linux, MacOS それぞれでビルド方法も違うので苦労しました・・・。

ライブラリの作成

今回は実際にライブラリの作成をしてみます。

最初は、Cygwin 上で gcc を使って dll を作成します。

早速の注意事項として、${JAVA_HOME}\include\win32\jni_md.h の型マッピングの定義が一致しないので対応しないといけません。

対応方法は、gcc 実行時に引数として -D__int64=’long long’ を定義する方法と、jni_md.h の jlong の定義を直接書き換える方法があります。

まずはコンパイルで sample.o ファイルを生成します。

gcc の -m はコンフィグ依存のオプションで、 no-cygwin によって Cygwin DLL とリンクしないように指定しています。

sample.o ができたら、さらにコンパイルして dll を生成します。

これで、dll の作成ができたので早速 Java プログラムを実行してみます。

コマンドラインからの実行方法は、java [クラス名] です。

次は Linux と Mac で使用するライブラリの作成方法についてまとめます。

LinuxとMacOS上でライブラリ作成

今回は、Linux と MacOS 上でライブラリを作成します。

まずは、オブジェクト(.oファイル)を作成します。

続いて、Linux の動的共有オブジェクト(.soファイル)を作成します。

Linux 上で、JDK1.5.0_13(Update13)を使用してネイティブコードを実行すると下記のエラーが出ます。

そこで、JDK1.5.0_09(Update9)にバージョンダウンしてみます。

古いバージョンのモジュールは「古いJDKのモジュールを探す」を参考にして下さい。

古いJDKのモジュールを探すJDK(J2SE)をダウンロードしようとしたら、公式サイトからは最新版へのリンクしか見当たらない。 というか、古いモジュールのダウンロー...

詳細はまだわかりませんが、JDK1.5.0_10(Update10)から内部的に何かが変わったみたいです。

わかり次第お伝えしようと思います。

JDK1.5.0_09(Update9)では問題なく実行が可能です。

次に、MacOS 上でのライブラリの作成です。Linux 同様に、オブジェクト(.oファイル)を作成します。

続いて、動的共有オブジェクト(.jnilibファイル)を作成します。MacOS では jnilib というファイルにしないと実現できないようです。

あとは、java コマンドで実行すると動作が確認できます。

Javaのサンプルプログラム

実際に作った Java のサンプルプログラムとヘッダファイルの紹介です。

今回は、下記の 4 つのメソッドを実装しています。

Java のソースコードは以下の通りです。

javah で生成したヘッダファイルは以下の通りです。

C++でプログラムを作成

今回は、C++ で作成したプログラムです。
(コメントは省いてます)

何か文字列を出力する簡単なサンプルを作ると、ついつい「Hello World」って書いちゃうのはなんででしょうか(笑)