MacOSX(Tiger)におけるJNIを利用したネイティブコード実行方法
8月 15, 2007
JNIとは
JNI(Java Native Interface)とはJava言語で開発されたプログラムから、
他の言語で開発されたネイティブコードのプログラムを利用するためのAPIである。
ネイティブコードとは、そのプラットフォームで実行可能なプログラムのこと。
JNIを利用することで、Java上で実行するのには速度面から難しいコードを、
ネイティブコードに書き換え、その部分だけ高速に実行できる。
また、JavaVMをネイティブコードから起動させることができるので、
Cのコードを実行していると見せかけてJavaのコードを呼ぶことができる。
#しかし、この場合はその環境にJREがインストールされている必要がある。
MacOSX(Tiger)でのJNI利用環境
当方の環境を以下に記す。
マシン:MacBook Intel Core2Duo 2GHz
JREのバージョン:1.5.0_07
java version “1.5.0_07″
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_07-164)
gccのバージョン:4.0.1
gcc version 4.0.1 (Apple Computer, Inc. build 5367)
JNI利用の流れ
今回はjavaコードの中でネイティブコードを呼び出す。
必要なソースは以下。
- HelloWorld.java
- HelloWorld.c
HelloWorld.javaの内容:
class HelloWorld {
private native void print();
static {
System.loadLibrary(“HelloWorld”);
}
public static void main(String[] args) {
new HelloWorld().print();
}
}
HelloWorld.cの内容:
#include <jni.h>
#include <stdio.h>
#include “HelloWorld.h”
JNIEXPORT void JNICALL
Java_HelloWorld_print(JNIEnv *env, jobject obj)
{
printf(“Hello World!\n”);
return;
}
実行に必要な処理をまとめる。
- HelloWorld.javaをコンパイルしてクラスファイル(HelloWorld.class)を生成
- javahを利用してHelloWorld.javaから、Cコードを生成する(HelloWorld.h)
- HelloWorld.hをインクルードしているHelloWorld.cをgccでコンパイルし、共有ライブラリを作る(libHelloWorld.jnilib)
- javaからコードを実行する
各々に対応するコマンドを示す。
1.HelloWorld.javaをコンパイルしてクラスファイル(HelloWorld.class)を生成
$javac HelloWorld.java
これでHelloWorld.classができる。
2. javahを利用してHelloWorld.javaから、Cコードを生成する(HelloWorld.h)
$javah -jni HelloWorld
.javaはつかない。おそらくclassファイルに対して実行しているからだと思われる。
このコマンドでHelloWorld.hが生成される。
3.HelloWorld.hをインクルードしているHelloWorld.cをgccでコンパイルし、共有ライブラリを作る(libHelloWorld.jnilib)
$ gcc -dynamiclib -o libHelloWorld.jnilib -I /System/Library/Frameworks/JavaVM.framework/Headers HelloWorld.c
linux向けの文書だと-sharedなどのオプションと書かれている場合が多いが、Macの場合は-dynamiclibである。
また、作成する共有ライブラリの命名はlib(名前).jnilibである必要がある。
4.javaからコードを実行する
$java HelloWorld
HelloWorld!と表示されたら成功。
ここで
Exception in thread “main” java.lang.UnsatisfiedLinkError: no HelloWorld in java.library.path
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1682)
at java.lang.Runtime.loadLibrary0(Runtime.java:822)
at java.lang.System.loadLibrary(System.java:992)
at HelloWorld.<clinit>(HelloWorld.java:4)
このようなエラーが出た場合、3.の手順での命名規則が間違っている可能性がある。
また、共有ライブラリのクラスパス(java.library.path)としてLD_LIBRARY_PATHを設定するという記事もあるが、
MacOSXの場合はDYLD_LIBRARY_PATHがそれに相当する上に、既に
.:/usr/lib:/usr/lib/java:/lib:/System/Library/Frameworks/JavaVM.framework/Versions/1.*/Libraries
が設定されているため、今回はlibHelloWorld.jnilibが同じディレクトリにあるので問題ない。
参考文献:
Java 28 – Project BuilderでJNIを作成させる:Apple Developer Connectionより
MacOSX10.4gccで共有ライブラリを作る:ブログ「がおがお」より
Java 2 Platform SE 1.3:クラスUnsatisfiedLinkError:Sun本家より
極めたい方は
Java Native Interface : Programmer’s Guide and Specification
PDFでダウンロードできる。
今後は、ネイティブからJavaVMを呼ぶコードについて記事を書くつもりだ。