| 目次 | 前項目 | 次項目 | Java ネイティブインタフェースの仕様 |
この呼び出し API により、ソフトウェアベンダは Java VM を任意のネイティブアプリケーションにロードできるようになります。そのベンダの提供する Java が実行可能なアプリケーションは、Java VM ソースコードにリンクする必要がありません。
本章では、呼び出し API の概要を述べ、その後ですべての呼び出し API 関数を説明します。
Main.test と呼ばれる static メソッドを起動します。明瞭にするために、エラーチェックを省略しました。
#include <jni.h> /* where everything is defined */
...
JavaVM *jvm; /* denotes a Java VM */
JNIEnv *env; /* pointer to native method interface */
JDK1_1InitArgs vm_args; /* JDK 1.1 VM initialization arguments */
/* Get the default initialization arguments and set the class
* path */
JNI_GetDefaultJavaVMInitArgs(&vm_args);
vm_args.classpath = ...;
/* load and initialize a Java VM, return a JNI interface
* pointer in env */
JNI_CreateJavaVM(&jvm, &env, &vm_args);
/* invoke the Main.test method using the JNI */
jclass cls = env->FindClass("Main");
jmethodID mid = env->GetStaticMethodID(cls, "test", "(I)V");
env->CallStaticVoidMethod(cls, mid, 100);
/* We are done. */
jvm->DestroyJavaVM();
この例では、API の3つの関数を使用しています。呼び出し API はネイティブアプリケーションが JNI インタフェースポインタを使用し VM 機能にアクセスできるようにします。この設計は Netscape の JRI 埋め込みインタフェースと同様です。
JNI_CreateJavaVM() 関数は Java VM をロードして初期化し、JNI インタフェースポインタにポインタを返します。JNI_CreateJavaVM() を呼び出したスレッドは、
メインスレッドとみなされます。
JNIEnv)は、現在のスレッドでのみ有効です。別のスレッドが Java VM にアクセスする必要がある場合、これは最初に
AttachCurrentThread() を呼び出し、それ自体を VM に接続し JNI インタフェースポインタを取得する必要があります。一度 VM に接続されると、ネイティブスレッドはネイティブメソッド内で実行中の普通の Java スレッドのように機能します。ネイティブスレッドは、それ自体を分離するために DetachCurrentThread() を呼び出すまで VM に接続されたままになります。
DestroyJavaVM() を呼び出す必要があります。さらに、メインスレッドは VM をアンロードできる唯一のスレッドです。
メインスレッドは、Java VM をアンロードするために DestroyJavaVM() 関数を呼び出すとき、Java VM 内で実行中の唯一のユーザスレッドである必要があります。ユーザスレッドには、Java スレッドおよび接続されたネイティブスレッドの両方があります。この制限は、Java スレッドまたは接続されたネイティブスレッドがロック、ウィンドウなどのシステムリソースを保持している可能性があるために存在します。DestroyJavaVM() 関数は、自動的にこれらのリソースを開放することはできません。VM がアンロードされているときに、メインスレッドを唯一の実行中のスレッドであると制限することで、任意のスレッドが保持するシステムリソースを開放する負荷はプログラマに課せられます。
次のコードは、JDK 1.1で java VM の初期化に使われる構造を示します。
typedef struct JavaVMInitArgs {
/* reserved fields */
jint reserved0;
void *reserved1;
/* whether to check the Java source files are newer than
* compiled class files. */
jint checkSource;
/* maximum native stack size of Java-created threads. */
jint nativeStackSize;
/* maximum Java stack size. */
jint javaStackSize;
/* initial heap size. */
jint minHeapSize;
/* maximum heap size. */
jint maxHeapSize;
/* controls whether Java byte code should be verified:
* 0 -- none, 1 -- remotely loaded code, 2 -- all code. */
jint verifyMode;
/* the local directory path for class loading. */
const char *classpath;
/* a hook for a function that redirects all VM messages. */
jint (*vfprintf)(FILE *fp, const char *format,
va_list args);
/* a VM exit hook. */
void (*exit)(jint code);
/* a VM abort hook. */
void (*abort)();
/* whether to enable class GC. */
jint enableClassGC;
/* whether GC messages will appear. */
jint enableVerboseGC;
/* whether asynchronous GC is allowed. */
jint disableAsyncGC;
} JDK1_1InitArgs;
JDK 1.1では、初期化構造が提供するフックにより、ネイティブアプリケーションは VM メッセージをリダイレクトすることができ、 VM 終了を制御することができるようになります。
次に示す構造は、ネイティブスレッドが JDK 1.1 の Java VM に接続するとき、引数として渡されます。実際、JDK 1.1 へ接続するためにネイティブスレッドが要求する引数はありません。JDK1_1AttachArgs 構造体は、空の構造を許さない C コンパイラ用の埋込みスロットだけから成ります。
typedef struct JDK1_1AttachArgs {
/*
* JDK 1.1 does not need any arguments to attach a
* native thread. The padding is here to satisfy the C
* compiler which does not permit empty structures.
*/
void *__padding;
} JDK1_1AttachArgs;
Java VM 型は呼び出し API 関数テーブルのポインタです。次のコード例では、この関数テーブルを示します。
typedef const struct JNIInvokeInterface *JavaVM;
const struct JNIInvokeInterface ... = {
NULL,
NULL,
NULL,
DestroyJavaVM,
AttachCurrentThread,
DetachCurrentThread,
};
次の 3 つの呼び出し API 関数に注意してください。
JNI_GetDefaultJavaVMInitArgs()、 JNI_GetCreatedJavaVMs()、および
JNI_CreateJavaVM()は、Java VM 関数ではありません。これらの関数は以前の JavaVM 構造がなくても使用することができます。
void JNI_GetDefaultJavaVMInitArgs(void *vm_args);
vm_args: デフォルト引数が入る VM-specific initialization 構造へのポインタ。
jint JNI_GetCreatedJavaVMs(JavaVM **vmBuf, jsize bufLen,
jsize *nVMs);
作成された Java VM をすべて返す。VM へのポインタは、作成された順にバッファ vmBuf に書き込まれます。しかし、エントリの bufLen 番号しか書き込みません。作成された VM の全体数は、*nVM で返します。
JDK 1.1 は 1 つのプロセスで、1 つの VM しかサポートしません。
vmBuf: VM 構造が配置されるバッファへのポインタ。
jint JNI_CreateJavaVM(JavaVM **p_vm, JNIEnv **p_env,
void *vm_args);
ロードして、Java VM を初期化します。カレントスレッドがメインスレッドになります。env 引数を、メインスレッドの JNI インタフェースポインタへ設定します。
JDK 1.1 は 1 つのプロセスで、1 つの VM しかサポートしません。
p_vm: 結果の VM 構造が配置される位置へのポインタ。
p_env: メインスレッドの JNI インタフェースポインタが配置される位置へのポインタ。
jint DestroyJavaVM(JavaVM *vm);
Java VM をアンロードし、そのリソースを回復します。メインスレッドだけが VM をアンロードできます。メインスレッドは DestroyJavaVM() を呼び出すとき、唯一残ったユーザスレッドでなければなりません。
vm: 破壊される Java VM。
jint AttachCurrentThread(JavaVM *vm, JNIEnv **p_env,
void *thr_args);
カレントスレッドを Java VM へ接続します。
JNIEnv 引数で JNI インタフェースポインタを返します。
すでに接続されているスレッドへの接続は、ノーオペレーションです。
ネイティブスレッドを 2 つの Java VM へ 同時に接続することはできません。
vm: カレントスレッドが接続される VM。
p_env: カレントスレッドの JNI インタフェースポインタが配置される位置へのポインタ。
jint DetachCurrentThread(JavaVM *vm);
Java VM からカレントスレッドを分離します。このスレッドが保持する Java モニタはすべて解放されます。このスレッドが終了するのを待つ Java スレッドすべてに、通知が行われます。
Java VM を作成するスレッドであるメインスレッドを、VM から分離することができません。その代わり、VM 全体をアンロードするために、メインスレッドは
JNI_DestroyJavaVM() を呼び出す必要があります。
vm: カレントスレッドが分離される VM。
Java ネイティブインタフェース仕様 (1997年3月15日に dkramer によって生成された HTML)
Copyright (C) 1996, 1997 Sun Microsystems, Inc.
All rights reserved
コメントは、jni@java.sun.com宛てに送ってください。