Dec 27, 2002 onlsbc1, Red Hat Linux 8.0 のシステムでのJNIの実行 --- hello world実行#1 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ (http://www-online.kek.jp/~inoue/para-CAMAC/ Work/SBC-Java3.html) 高エネルギー加速器研究機構 素粒子原子核研究所 物理、オンライングループ 井上 栄二 目的 SBC、PCM-9370にインストールしてある Red Hat Linux 8.0 のシステム上で JNIを使って Hello Word が実行できることを確認する。 (1). 構成 (2). コンパイル (3). 実行 -------------------------------------------------------------------- (1). 構成 テストに使用するマシンは onlsbc1 である。 このマシンはアドバンテク社の SBC、PCM-9370である。 動作している OSはRed Hat Linux 8.0 で、Javaの バージョンは1.4.1_01 である。 最終的にはコンパクトフラッシュ上に構成した Linuxシステムで実行できることを目指すのであるが、ソフトウェアの開発段階 では 2.5" IDE ハードディスク上に構成したLinuxシステムを使ってテストを 行うことにする。 (2). コンパイル (2-1). Javaのチェック [inoue@onlsbc1 inoue]$ java -version java version "1.4.1_01" Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.1_01-b01) Java HotSpot(TM) Client VM (build 1.4.1_01-b01, mixed mode) [inoue@onlsbc1 inoue]$ (2-2). 実行環境 [inoue@onlsbc1 JNI]$ env MANPATH=:/usr/java/man HOSTNAME=onlsbc1.kek.jp PVM_RSH=/usr/bin/rsh TERM=vt100 SHELL=/bin/bash JLESSCHARSET=japanese HISTSIZE=1000 SSH_CLIENT=130.87.153.9 33049 22 QTDIR=/usr/lib/qt3-gcc3.2 SSH_TTY=/dev/pts/1 USER=inoue LS_COLORS=no=00:fi=00:di=01;34:ln=01;36:pi=40;33:so=01;35:bd=40;33;01:cd=40;33;0 1:or=01;05;37;41:mi=01;05;37;41:ex=01;32:*.cmd=01;32:*.exe=01;32:*.com=01;32:*.b tm=01;32:*.bat=01;32:*.sh=01;32:*.csh=01;32:*.tar=01;31:*.tgz=01;31:*.arj=01;31: *.taz=01;31:*.lzh=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.gz=01;31:*.bz2=01;31:* .bz=01;31:*.tz=01;31:*.rpm=01;31:*.cpio=01;31:*.jpg=01;35:*.gif=01;35:*.bmp=01;3 5:*.xbm=01;35:*.xpm=01;35:*.png=01;35:*.tif=01;35: PVM_ROOT=/usr/share/pvm3 MAIL=/var/spool/mail/inoue PATH=/usr/kerberos/bin:/usr/local/bin:/bin:/usr/bin:/usr/X11R6/bin:/usr/java/bin :/home/inoue/bin INPUTRC=/etc/inputrc PWD=/home/inoue/JNI LANG=ja_JP.eucJP LAMHELPFILE=/etc/lam/lam-helpfile SSH_ASKPASS=/usr/libexec/openssh/gnome-ssh-askpass SHLVL=1 HOME=/home/inoue XPVM_ROOT=/usr/share/pvm3/xpvm LOGNAME=inoue LESSOPEN=|/usr/bin/lesspipe.sh %s G_BROKEN_FILENAMES=1 _=/bin/env OLDPWD=/home/inoue [inoue@onlsbc1 JNI]$ (2-3). Javaコードを書く この実行で使用するソースコードは、以下のURLから入手した。 http://java.sun.com/j2se/1.4/ja/docs/ja/guide/jni/index.html [inoue@onlsbc1 JNI]$ cat HelloWorld.java class HelloWorld { public native void displayHelloWorld(); static { System.loadLibrary("hello"); } public static void main(String[] args) { new HelloWorld().displayHelloWorld(); } } [inoue@onlsbc1 JNI]$ (2-4). Javaコードをコンパイルする [inoue@onlsbc1 JNI]$ ls -l 合計 4 -rw-rw-r-- 1 inoue inoue 224 12月 26 17:01 HelloWorld.java [inoue@onlsbc1 JNI]$ javac HelloWorld.java [inoue@onlsbc1 JNI]$ ls -l 合計 8 -rw-rw-r-- 1 inoue inoue 462 12月 26 17:05 HelloWorld.class -rw-rw-r-- 1 inoue inoue 224 12月 26 17:01 HelloWorld.java [inoue@onlsbc1 JNI]$ (2-5). .hファイルの生成 C++言語のヘッダーファイルは、以下のようにjavahというコマンドで生成 できる。 オプションには-jniを指定し、引数には項目(2-4)でコンパイルした クラスの拡張子を除いたものを指定する。 [inoue@onlsbc1 JNI]$ javah -jni HelloWorld [inoue@onlsbc1 JNI]$ ls -l 合計 12 -rw-rw-r-- 1 inoue inoue 462 12月 26 17:05 HelloWorld.class -rw-rw-r-- 1 inoue inoue 401 12月 26 17:13 HelloWorld.h -rw-rw-r-- 1 inoue inoue 224 12月 26 17:01 HelloWorld.java [inoue@onlsbc1 JNI]$ cat HelloWorld.h /* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class HelloWorld */ #ifndef _Included_HelloWorld #define _Included_HelloWorld #ifdef __cplusplus extern "C" { #endif /* * Class: HelloWorld * Method: displayHelloWorld * Signature: ()V */ JNIEXPORT void JNICALL Java_HelloWorld_displayHelloWorld (JNIEnv *, jobject); #ifdef __cplusplus } #endif #endif [inoue@onlsbc1 JNI]$ (2-6). C言語のソースファイルの作成 [inoue@onlsbc1 JNI]$ cat HelloWorldImp.c #include <jni.h> #include "HelloWorld.h" #include <stdio.h> JNIEXPORT void JNICALL Java_HelloWorld_displayHelloWorld(JNIEnv *env, jobject obj) { printf("Hello world!\n"); return; } [inoue@onlsbc1 JNI]$ (2-7). C言語のソースファイルをコンパイルしてシェアード・ライブラリを作成 [inoue@onlsbc1 JNI]$ pwd /home/inoue/JNI [inoue@onlsbc1 JNI]$ ls -l 合計 16 -rw-rw-r-- 1 inoue inoue 462 12月 26 17:05 HelloWorld.class -rw-rw-r-- 1 inoue inoue 401 12月 26 17:13 HelloWorld.h -rw-rw-r-- 1 inoue inoue 224 12月 26 17:01 HelloWorld.java -rw-rw-r-- 1 inoue inoue 192 12月 26 17:17 HelloWorldImp.c [inoue@onlsbc1 JNI]$ [inoue@onlsbc1 JNI]$ ls -l /usr/java/include 合計 152 -r--r--r-- 1 root root 8497 9月 30 19:13 jawt.h -r--r--r-- 1 root root 67553 9月 30 19:13 jni.h -r--r--r-- 1 root root 39103 9月 30 19:13 jvmdi.h -r--r--r-- 1 root root 21994 9月 30 19:13 jvmpi.h drwxr-xr-x 2 root root 4096 9月 30 19:13 linux [inoue@onlsbc1 JNI]$ ls -l /usr/java/include/linux 合計 8 -r--r--r-- 1 root root 947 9月 30 19:13 jawt_md.h -r--r--r-- 1 root root 453 9月 30 19:13 jni_md.h [inoue@onlsbc1 JNI]$ [inoue@onlsbc1 JNI]$ gcc -G -I/usr/java/include -I/usr/java/include/linux HelloW orldImp.c -o libhello.so gcc: 認識不能なオプション `-G' /usr/lib/gcc-lib/i386-redhat-linux/3.2/../../../crt1.o: In function `_start': /usr/lib/gcc-lib/i386-redhat-linux/3.2/../../../crt1.o(.text+0x18): undefined re ference to `main' collect2: ld はステータス 1 で終了しました [inoue@onlsbc1 JNI]$ SUNコンパイラの cc の man をチェック。 onlsun1[36]% man cc User Commands cc(1) 名前 cc - C コンパイラ 形式 cc [ -# ] [ -### ] [ -A <名前>[(<トークン>)] ] [ -B[static|dynamic] ] [ -C ] [ -c ] : : -G このオプションを指定すると、リンカーは、動的にリンクさ れた実行可能ファイルではなく、共有オブジェクトを作成し ます。このオプションは ld に渡されます。 -dn オプション と一緒に使用することはできません。 : onlsun1[37]% Linuxの gcc の man をチェック。 [inoue@onlsbc1 JNI]$ man gcc 名称 gcc, g++ - GNU プロジェクト C および C++ コンパイラ (gcc-2.95.3) 書式 gcc [ option | filename ]... : : こ こに追加するオプションは System V Release 4 において、これらのシステ ム上の他のコンパイラとの互換性のために提供されるものです。 -G SVr4 システムにおいて、gcc は `-G' オプションを受け付けます ( そ し てこれをシステムリンカに渡します)。これは他のコンパイラとの互 換性のためです。しかし、リンカオプションを gcc のコマンドライ ン から渡すよりも、我々は `-symbolic' または `-shared' の使用が適当 であると考えています。 [inoue@onlsbc1 JNI]$ gcc -shared -I/usr/java/include -I/usr/java/include/linux H elloWorldImp.c -o libhello.so [inoue@onlsbc1 JNI]$ ls -l 合計 24 -rw-rw-r-- 1 inoue inoue 462 12月 26 17:05 HelloWorld.class -rw-rw-r-- 1 inoue inoue 401 12月 26 17:13 HelloWorld.h -rw-rw-r-- 1 inoue inoue 224 12月 26 17:01 HelloWorld.java -rw-rw-r-- 1 inoue inoue 192 12月 26 17:17 HelloWorldImp.c -rwxrwxr-x 1 inoue inoue 5658 12月 27 09:10 libhello.so [inoue@onlsbc1 JNI]$ (3). 実行 [inoue@onlsbc1 JNI]$ pwd /home/inoue/JNI [inoue@onlsbc1 JNI]$ ls -l 合計 24 -rw-rw-r-- 1 inoue inoue 462 12月 26 17:05 HelloWorld.class -rw-rw-r-- 1 inoue inoue 401 12月 26 17:13 HelloWorld.h -rw-rw-r-- 1 inoue inoue 224 12月 26 17:01 HelloWorld.java -rw-rw-r-- 1 inoue inoue 192 12月 26 17:17 HelloWorldImp.c -rwxrwxr-x 1 inoue inoue 5658 12月 27 09:10 libhello.so [inoue@onlsbc1 JNI]$ java HelloWorld Exception in thread "main" java.lang.UnsatisfiedLinkError: no hello in java.libr ary.path at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1403) at java.lang.Runtime.loadLibrary0(Runtime.java:788) at java.lang.System.loadLibrary(System.java:832) at HelloWorld.<clinit>(HelloWorld.java:5) [inoue@onlsbc1 JNI]$ ライブラリpathが正しくセットされていない。 [inoue@onlsbc1 JNI]$ export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH [inoue@onlsbc1 JNI]$ java HelloWorld Hello world! [inoue@onlsbc1 JNI]$ ok. JNIによる Hello World は正常に実行できた。 ---xxxx