JNI (Java Native Interface)は、Java仮想マシンとネイティブアプリケーションを組み合わせるための標準プログラミングインタフェースです。
Java   VM の動作に影響を及ぼすので、JNI関数の中ではシグナルハンドラを設定してはいけません。J2SDK   v1.4からシグナル連鎖機能がサポートされ、シグナルハンドラが使用できるようになった。
Javaから呼び出されているネイティブライブラリをデバッガで動作させる
Javaから呼び出されているネイティブライブラリをデバッガで動作させるには、環境変数DEBUG_PROGにデバッガを定義します。そしてJavaを実行させるとデバッガが起動されますので、stop dlopenコマンドでデバッグするライブラリのパスを指定します。runコマンドで実行すると、libxxx.soが呼び出されると停止するので、ブレークポイントを設定して実行を継続します。
$ java
(dbx) stop dlopenn ライブラリのパス
(dbx) run Test.Test_0
(dbx) file operate.c
(dbx) stop at 行番号
(dbx) cont
JNIを使ってC言語からJavaのメソッドを呼ぶ
JNIを使うと、ネイティブ・コード(C言語やC++など)からJavaのクラスを利用したり、メソッドを呼ぶことができる。
C言語のサンプル・コードを次に示す。
include "jni.h"    int main()  {      JNIEnv  *env;      JavaVM  *jvm;      int     res;      jclass  clazz;      jmethodID mid;        JavaVMOption options[3];      options[0].optionString = "-Xmx128m";      options[1].optionString = "-verbose:gc";      options[2].optionString = "-Djava.class.path=/home/yajima/class";        JavaVMInitArgs vm_args;      vm_args.version = JNI_VERSION_1_6;      vm_args.options = options;      vm_args.nOptions = 3;        /* Java VM の作成 */      res = JNI_CreateJavaVM(&jvm, (void **)&env, &vm_args);      if (res < 0) {          fprintf(stderr, "JNI_CreateJavaVM error\n");          return -1;      }        /* Javaクラスの検索 */      clazz = (*env)->FindClass(env, "Hello");      if (clazz == 0) {          fprintf(stderr, "FindClass error\n");          return -1;      }        /* メソッド識別子の取得 */      mid = (*env)->GetStaticMethodID(env, clazz, "main",          "([Ljava/lang/String;)V");      if (mid == 0) {          fprintf(stderr, "GetStaticMethodID error\n");          return -1;      }        /* Hello#main の呼び出し */      (*env)->CallStaticVoidMethod(env, clazz, mid, NULL);        /* Java VM の破棄 */      (*jvm)->DestroyJavaVM(jvm);        return 0;  }    C言語から呼び出されるJavaのサンプル・コードを次に示す。
public class Hello {      public static void main(String args[]) {          System.out.println("Hello!");      }  }    jni.h のインクルード
C言語/C++   のプログラムで、ヘッダファイル jni.h をインクルードする必要がある。jni.h は JDK_HOME/include ディレクトリに含まれているので、このディレクトリをインクルードファイルのディレクトリとしてコンパイラに指定する。
jni.h の中では jni_md.h をインクルードしている。jni_md.h にはプラットフォームに依存する内容が含まれている。そのため、jni_md.h が存在するディレクトリはプラットフォームにより異なる。このディレクトリもインクルードファイルのディレクトリとしてコンパイラに指定する。
jni_md.h が存在するディレクトリの一例を次に示す。
| OS | パス | 
|---|---|
| Windows | include\win32 | 
| Linux | include/linux | 
| Solaris | include/solaris | 
JNI変数型のマッピング
Javaとネイティブ変数型(C言語)のマッピングを次の表に示す。
| Java変数型 | ネイティブ変数型 | 
|---|---|
| jboolean | unsigned char | 
| jbyte | signed char | 
| jchar | unsigned short | 
| jshort | short | 
| jnit | int | 
| jlong | long long __int64 | 
| jfloat | float | 
| jdouble | double | 
Java VMの生成
Java VMをロードして初期化するには、JNI_CreateJavaVM()関数を呼び出す。
JNI_CreateJavaVM(JavaVM **pvm, void **penv, void *args);
引数pvmには、呼び出しAPI関数テーブルのポインタ (JavaVM *) を格納する領域へのポインタを渡す。
呼び出しAPI関数テーブルには、次に示す関数へのポインタが格納される。
- DestroyJavaVM
- AttachCurrentThread
- DetachCurrentThread
- GetEnv
- AttachCurrentThreadAsDaemon
引数argsには、JavaVMInitArgs構造体を参照するポインタを指定する。
JavaVM型
JavaVM は、JNIInvokeInterface_ 構造体へのポインタ型である。
#ifdef __cplusplus typedef JavaVM_ JavaVM; #else typedef const struct JNIInvokeInterface_ *JavaVM;
 
0 件のコメント:
コメントを投稿