Android JNI学習(4) - JNIの共通メソッドの中国語API

 この一連の記事は次のとおりです。

Android JNIの学習(1) - NDKとJNIの基本
Android JNIの学習(2) - 実際のJNIの「hello world」
Android JNIの学習(3) - Javaとネイティブの呼び出し
Android JNIの学習(4) - 共通のJNI中国語APIメソッド

この記事は主に、 JNI で一般的に使用される API をより深く理解するために役立つ、JNIの共通インターフェイス ドキュメントの翻訳に基づいています。詳細は次のとおりです。

1. インターフェース機能テーブル(インターフェース機能テーブル)

各関数には、JNIEnv パラメータを介してアクセスできます。JNIEnv 型は、すべての JNI インターフェイス ポインタを格納するためのポインタです。次のように定義されます。

typedef const struct JNINativeInterface *JNIEnv;

仮想マシン初期化関数テーブル。次のコードに示すように、最初の 3 つのエントリは、将来の COM との互換性のために予約されています。また、たとえば、将来のクラス関連の JNI 操作をテーブルの末尾ではなく FindClass の後に追加できるように、関数テーブルの先頭近くにいくつかの追加の NULL エントリを保持します。関数テーブルはすべての JNI インターフェイス ポインター間で共有できることに注意してください。

まず、JNINativeInterface を見てみましょう。

const struct JNINativeInterface ... = {

    NULL,
    NULL,
    NULL,
    NULL,
    GetVersion,

    DefineClass,
    FindClass,

    FromReflectedMethod,
    FromReflectedField,
    ToReflectedMethod,

    GetSuperclass,
    IsAssignableFrom,

    ToReflectedField,

    Throw,
    ThrowNew,
    ExceptionOccurred,
    ExceptionDescribe,
    ExceptionClear,
    FatalError,

    PushLocalFrame,
    PopLocalFrame,

    NewGlobalRef,
    DeleteGlobalRef,
    DeleteLocalRef,
    IsSameObject,
    NewLocalRef,
    EnsureLocalCapacity,

    AllocObject,
    NewObject,
    NewObjectV,
    NewObjectA,

    GetObjectClass,
    IsInstanceOf,

    GetMethodID,

    CallObjectMethod,
    CallObjectMethodV,
    CallObjectMethodA,
    CallBooleanMethod,
    CallBooleanMethodV,
    CallBooleanMethodA,
    CallByteMethod,
    CallByteMethodV,
    CallByteMethodA,
    CallCharMethod,
    CallCharMethodV,
    CallCharMethodA,
    CallShortMethod,
    CallShortMethodV,
    CallShortMethodA,
    CallIntMethod,
    CallIntMethodV,
    CallIntMethodA,
    CallLongMethod,
    CallLongMethodV,
    CallLongMethodA,
    CallFloatMethod,
    CallFloatMethodV,
    CallFloatMethodA,
    CallDoubleMethod,
    CallDoubleMethodV,
    CallDoubleMethodA,
    CallVoidMethod,
    CallVoidMethodV,
    CallVoidMethodA,

    CallNonvirtualObjectMethod,
    CallNonvirtualObjectMethodV,
    CallNonvirtualObjectMethodA,
    CallNonvirtualBooleanMethod,
    CallNonvirtualBooleanMethodV,
    CallNonvirtualBooleanMethodA,
    CallNonvirtualByteMethod,
    CallNonvirtualByteMethodV,
    CallNonvirtualByteMethodA,
    CallNonvirtualCharMethod,
    CallNonvirtualCharMethodV,
    CallNonvirtualCharMethodA,
    CallNonvirtualShortMethod,
    CallNonvirtualShortMethodV,
    CallNonvirtualShortMethodA,
    CallNonvirtualIntMethod,
    CallNonvirtualIntMethodV,
    CallNonvirtualIntMethodA,
    CallNonvirtualLongMethod,
    CallNonvirtualLongMethodV,
    CallNonvirtualLongMethodA,
    CallNonvirtualFloatMethod,
    CallNonvirtualFloatMethodV,
    CallNonvirtualFloatMethodA,
    CallNonvirtualDoubleMethod,
    CallNonvirtualDoubleMethodV,
    CallNonvirtualDoubleMethodA,
    CallNonvirtualVoidMethod,
    CallNonvirtualVoidMethodV,
    CallNonvirtualVoidMethodA,

    GetFieldID,

    GetObjectField,
    GetBooleanField,
    GetByteField,
    GetCharField,
    GetShortField,
    GetIntField,
    GetLongField,
    GetFloatField,
    GetDoubleField,
    SetObjectField,
    SetBooleanField,
    SetByteField,
    SetCharField,
    SetShortField,
    SetIntField,
    SetLongField,
    SetFloatField,
    SetDoubleField,

    GetStaticMethodID,

    CallStaticObjectMethod,
    CallStaticObjectMethodV,
    CallStaticObjectMethodA,
    CallStaticBooleanMethod,
    CallStaticBooleanMethodV,
    CallStaticBooleanMethodA,
    CallStaticByteMethod,
    CallStaticByteMethodV,
    CallStaticByteMethodA,
    CallStaticCharMethod,
    CallStaticCharMethodV,
    CallStaticCharMethodA,
    CallStaticShortMethod,
    CallStaticShortMethodV,
    CallStaticShortMethodA,
    CallStaticIntMethod,
    CallStaticIntMethodV,
    CallStaticIntMethodA,
    CallStaticLongMethod,
    CallStaticLongMethodV,
    CallStaticLongMethodA,
    CallStaticFloatMethod,
    CallStaticFloatMethodV,
    CallStaticFloatMethodA,
    CallStaticDoubleMethod,
    CallStaticDoubleMethodV,
    CallStaticDoubleMethodA,
    CallStaticVoidMethod,
    CallStaticVoidMethodV,
    CallStaticVoidMethodA,

    GetStaticFieldID,

    GetStaticObjectField,
    GetStaticBooleanField,
    GetStaticByteField,
    GetStaticCharField,
    GetStaticShortField,
    GetStaticIntField,
    GetStaticLongField,
    GetStaticFloatField,
    GetStaticDoubleField,

    SetStaticObjectField,
    SetStaticBooleanField,
    SetStaticByteField,
    SetStaticCharField,
    SetStaticShortField,
    SetStaticIntField,
    SetStaticLongField,
    SetStaticFloatField,
    SetStaticDoubleField,

    NewString,

    GetStringLength,
    GetStringChars,
    ReleaseStringChars,

    NewStringUTF,
    GetStringUTFLength,
    GetStringUTFChars,
    ReleaseStringUTFChars,

    GetArrayLength,

    NewObjectArray,
    GetObjectArrayElement,
    SetObjectArrayElement,

    NewBooleanArray,
    NewByteArray,
    NewCharArray,
    NewShortArray,
    NewIntArray,
    NewLongArray,
    NewFloatArray,
    NewDoubleArray,

    GetBooleanArrayElements,
    GetByteArrayElements,
    GetCharArrayElements,
    GetShortArrayElements,
    GetIntArrayElements,
    GetLongArrayElements,
    GetFloatArrayElements,
    GetDoubleArrayElements,

    ReleaseBooleanArrayElements,
    ReleaseByteArrayElements,
    ReleaseCharArrayElements,
    ReleaseShortArrayElements,
    ReleaseIntArrayElements,
    ReleaseLongArrayElements,
    ReleaseFloatArrayElements,
    ReleaseDoubleArrayElements,

    GetBooleanArrayRegion,
    GetByteArrayRegion,
    GetCharArrayRegion,
    GetShortArrayRegion,
    GetIntArrayRegion,
    GetLongArrayRegion,
    GetFloatArrayRegion,
    GetDoubleArrayRegion,
    SetBooleanArrayRegion,
    SetByteArrayRegion,
    SetCharArrayRegion,
    SetShortArrayRegion,
    SetIntArrayRegion,
    SetLongArrayRegion,
    SetFloatArrayRegion,
    SetDoubleArrayRegion,

    RegisterNatives,
    UnregisterNatives,

    MonitorEnter,
    MonitorExit,

    GetJavaVM,

    GetStringRegion,
    GetStringUTFRegion,

    GetPrimitiveArrayCritical,
    ReleasePrimitiveArrayCritical,

    GetStringCritical,
    ReleaseStringCritical,

    NewWeakGlobalRef,
    DeleteWeakGlobalRef,

    ExceptionCheck,

    NewDirectByteBuffer,
    GetDirectBufferAddress,
    GetDirectBufferCapacity,

    GetObjectRefType
  };

以下、詳しくご紹介していきます

2. JNI バージョン情報を取得する

JNIEnv ポインタには、JNI のバージョンを取得する関数があります。

jint GetVersion(JNIEnv *env);

このメソッドは主に、ローカル JNI メソッド インターフェイスのバージョン情報を返します。戻り値は、JDK 環境によって次のように異なります。

  • JDK/JRE 1.1 では、0x00010001 を返します。
  • JDK/JRE 1.2 では、0x00010002 を返します。
  • JDK/JRE 1.3 では、0x00010004 を返します。
  • JDK/JRE 1.4 では、0x00010006 を返します。

上記の数値は私がランダムに取得したものではなく、実際には次のように長い間マクロとして定義されていました。

#define JNI_VERSION_1_1 0x00010001
#define JNI_VERSION_1_2 0x00010002

/* Error codes */
#define JNI_EDETACHED    (-2)              /* thread detached from the VM */
#define JNI_EVERSION     (-3)              /* JNI version error 
SINCE JDK/JRE 1.4:
    #define JNI_VERSION_1_4 0x00010004
SINCE JDK/JRE 1.6:
    #define JNI_VERSION_1_6 0x00010006

3. Javaクラスの操作

(1)、クラスの定義(クラスのロード)

jclass DefineClass(JNIEnv *env,const char* name,jobject loader,const jbyte *buf, jsize bufLen)

この関数は主に、データを含むバッファからクラスをロードします。このバッファには、クラスの呼び出し時に仮想マシンによって参照されない元のクラス データが含まれます。

エントリーの説明:

  • env: JNI インターフェイス ポインタ
  • name: 定義されたクラス名またはインターフェイス名。文字列は修正された UTF-8 エンコーディングを持ちます。
  • ローダー: 定義されたクラスローダーに割り当てられます。
  • buf: .class ファイルデータを含むバッファ
  • bufLen: バッファ長

戻り値: Java クラス オブジェクト。エラーが発生した場合は NULL を返します。

スローされる可能性のある例外:

  • Java クラスが指定されていない場合は、ClassFormatError がスローされます。
  • クラス/インターフェイスがそれ自体のスーパークラス/スーパーインターフェイスである場合、ClassCircularityError がスローされます。
  • メモリ不足の場合は OutOfMemoryError がスローされます
  • Java パッケージ内でクラスを定義しようとすると、SecurityException がスローされます。

(2)、検索クラス

jclass FindClass(JNIEnv *env,const char *name);

ここには 2 つの状況があり、1 つは JDK リリース 1.1 で、もう 1 つは JDK リリース 1.2 です。JDK リリース 1.1 以降、この関数はローカルに定義されたクラスをロードし、CLASSPATH 環境変数内のディレクトリと zip ファイルで特定の名前のクラスを検索します。Java 2 リリース 1.2 以降、Java セキュリティ モデルでは、非システム クラスのロードとネイティブ メソッドの呼び出しが許可されています。FindClass は、現在のネイティブ メソッドに関連付けられたクラス ローディング、つまり、ネイティブ メソッドを宣言するクラスのクラス ローディング クラスを定義します。ネイティブ メソッドがシステム クラスに属している場合、クラス ローダーは関係しません。それ以外の場合は、適切なクラス ローディングが呼び出され、指定されたクラスをロードしてリンクします。Java 2 SDK 1.2 以降、呼び出し側インターフェイスを介して FindClass を呼び出す場合、現在のネイティブ メソッドまたは関連するクラス ローダーは存在しません。この場合、ClassLoader.getSystemClassLoader の結果を使用します。これは、仮想マシンがアプリケーション用に作成するクラス ローダーであり、java.class.path プロパティにリストされているクラスを検索できます。

エントリーの説明:

  • env: JNI インターフェイス ポインタ
  • name: 完全修飾クラス名。「パッケージ名」+「/」+クラス名が含まれます。例: java.lang.String など、パラメータは java/lang/String で、クラス名が [ で始まる場合、配列クラスが返されます。たとえば、配列クラスのシグネチャは java.lang.Object[] で、パラメータは「[Ljava/lang/Object」である必要があります。

戻る:

  • 対応する完全修飾クラス オブジェクトを返します。クラスが見つからない場合は、NULL を返します。

スローされる可能性のある例外:

  • Java クラスが指定されていない場合は、ClassFormatError がスローされます。
  • クラス/インターフェイスがそれ自体のスーパークラス/スーパーインターフェイスである場合、ClassCircularityError がスローされます。
  • クラス/インターフェイスの定義が見つからない場合は、NoClassDefFoundError がスローされます
  • メモリ不足の場合は OutOfMemoryError がスローされます

(3)、親クラスを見つけます

jclass GetSuperclass(JNIEnv *env,jclass clazz);

clazz が Object クラスでない場合、この関数はこの clazz の親クラスを表す Class オブジェクトを返します。クラスが Object であるか、clazz がインターフェイスを表す場合、この関数は NULL を返します。

エントリーの説明:

  • env: JNI インターフェイス ポインタ
  • clazz: Java クラス クラス

戻る:

  • clazz の親クラスがある場合はその親クラスを返し、ない場合は NULL を返します。

(4)、安全な変換

jboolean IsAssignableFrom(JNIEnv *env,jclass clazz1,jclass clazz2);

clazz1 のオブジェクトを clazz2 のオブジェクトに安全に変換できるかどうかを判断します。

エントリーの説明:

  • env: JNI インターフェイス ポインタ
  • clazz1: Java の Class クラス、つまり変換する必要があるクラス
  • clazz2: Java の Class クラス、つまりターゲットに変換する必要があるクラス

戻る:

次の条件のいずれかが true の場合、JNI_TRUE を返します。

  • clazz1 と clazz2 が同じ Java クラスの場合。
  • clazz1 が clazz2 のサブクラスの場合
  • clazz1 が clazz2 インターフェースの実装クラスの場合

4. 異常動作

(1)、例外をスローします

jint Throw(JNIEnv *env,jthrowable obj);

jthrowable オブジェクトを渡し、それを JNI にスローします。

エントリーの説明:

  • env: JNI インターフェイス ポインタ
  • jthrowable: Java java.lang.Throwable オブジェクト

戻る:

  • 成功した場合は 0 を返し、失敗した場合は負の数を返します。

スローされる可能性のある例外:

  • java.lang.Throwable オブジェクトをスローします

(2) 新しい例外を構築してスローする

jint ThrowNew(JNIEnv *env,jclass clazz,const char* message);

メッセージを渡し、それを使用して例外を構築し、スローします。

エントリーの説明:

  • env: JNI インターフェイス ポインタ
  • jthrowable: Java java.lang.Throwable オブジェクト
  • message: java.lang.Throwable オブジェクトの構築に使用されるメッセージ。文字列は修正された UTF-8 でエンコードされます。

戻る:

  • 成功した場合は 0 を返し、失敗した場合は負の数を返します。

スローされる可能性のある例外:

  • 新しく構築された java.lang.Throwable オブジェクトをスローします

(3) 例外が発生したかどうかを確認し、例外をスローする

jthrowable ExceptionOccurred(JNIEnv *env);

例外が発生したかどうかを確認し、発生した場合は (ExceptionClear() 関数を呼び出す前、または Java が例外を処理する前に) 例外への参照を返し、例外が発生しない場合は NULL を返します。

エントリーの説明:

  • env: JNI インターフェイス ポインタ

戻る:

  • jthrowable の例外参照または NULL

(4) スタック異常情報を出力する

void ExceptionDescribe(JNIEnv *env)

例外のスタック トレースを出力します。

エントリーの説明:

  • env: JNI インターフェイス ポインタ

(5) 例外スタック情報のクリア

void ExceptionClear(JNIEnv *env);

スローされている例外をクリアします。現在例外がスローされていない場合、この関数は効果がありません。

エントリーの説明:

  • env: JNI インターフェイス ポインタ

(6)、致命的な例外

void FatalError(JNIEnv *env,const char* msg);

致命的例外は、例外メッセージを出力し、現在の VM インスタンスを終了する、つまりプログラムを終了するために使用されます。

エントリーの説明:

  • env: JNI インターフェイス ポインタ
  • msg: 例外のエラー メッセージ。文字列は修正された UTF-8 でエンコードされます。

(7)、例外が発生するかどうかを確認するだけです

jboolean ExceptionCheck(JNIEnv *env);

例外が発生したかどうかを確認し、例外が発生した場合は JNI_TRUE を返し、例外が発生した場合は JNI_FALSE を返します。

エントリーの説明:

  • env: JNI インターフェイス ポインタ

戻る:

  • 例外が発生した場合は JNI_TRUE を返し、例外が発生していない場合は JNI_FALSE を返します。

5. グローバル参照とローカル参照

(1) グローバル参照の作成

jobject NewGlobalRef(JNIEnv *env,object obj);

オブジェクト obj へのグローバル参照を作成します。obj はグローバル参照またはローカル参照にすることができます。グローバル参照は、DeleteGlobalRef() を介して明示的に処理する必要があります。

パラメータの説明:

  • env: JNI インターフェイス ポインタ
  • obj: オブジェクト オブジェクト

戻る:

  • jobject へのグローバル参照、メモリ不足の場合は NULL を返す

(2)、グローバル参照を削除します

void DeleteGlobalRef(JNIEnv *env,jobject globalRef);

グローバル参照を削除します。

パラメータの説明:

  • env: JNI インターフェイス ポインタ
  • globalRef: 削除する必要があるグローバル参照

(3) ローカル参照の削除

ローカル参照は、ネイティブ インターフェイス呼び出しの存続期間中のみ有効であり、ネイティブ メソッドが返されると自動的に解放されます。各ローカル参照は、一定量の仮想マシン リソースを消費します。ローカル参照は自動的に破棄できますが、プログラマは、ローカル メソッドでローカル参照を過剰に割り当てないように注意する必要もあります。ローカル参照の過剰な割り当ては、仮想マシンのメモリ不足を引き起こします。ローカルメソッドを実行するとオーバーフローが発生します。

void DeleteLocalRef(JNIEnv *env, jobject localRef); 

localRef を介してローカル参照を削除します。

パラメータの説明

  • env: JNI インターフェイス ポインタ
  • localRef: 削除する必要があるローカル参照

JDK/JRE 1.1 は、プログラマが手動でローカル参照を削除できるように、上記の DeleteLocalRef 関数を提供します。

JDK/JRE 1.2からは、以下の4つのライフサイクル管理機能群が提供されています。

(4) ローカル変数の容量を設定する

jint EnsureLocalCapacity(JNIEnv *env,jint capacity);

現在のスレッドでは、容量、capacity を渡すことによって作成されるローカル参照の数を制限します。成功した場合は 0 を返し、それ以外の場合は負の数を返し、OutOfMemoryError をスローします。VM は、少なくとも 16 個のローカル参照を作成できることを自動的に保証します。

パラメータの説明

  • env: JNI インターフェイス ポインタ
  • capacity:容量

戻る:

  • 成功すると 0 が返され、失敗すると負の数が返され、OutOfMemoryError がスローされます。

下位互換性のため、仮想マシンが容量を超えるローカル参照を作成する場合。VM は FatalError を呼び出して、これ以上ローカル参照が作成できないようにします。(デバッグ モードの場合、仮想マシンはユーザーに警告を発行し、さらにローカル参照が作成されたことを知らせます。JDK では、プログラマは -verbose: jni コマンド ライン オプションを指定して、このメッセージを開くことができます)

(5) 古いフレームの上に新しいフレームを作成します

jint PushLocalFram(JNIEnv *env ,jint capacity);

ローカル変数容量が設定されている場合は、ローカル変数コンテナを再作成します。成功すると 0 が返され、失敗すると負の数が返され、OutOfMemoryError 例外がスローされます。

注: 現在のローカル フレームでは、前のローカル フレームによって作成されたローカル参照はまだ有効です。

パラメータの説明

  • env: JNI インターフェイス ポインタ
  • capacity:容量

(6)、ローカル参照を解放します。

jobject PopLocalFrame(JNIEnv *env,jobject result)

現在のローカル参照フレームをポップし、すべてのローカル参照を解放します。前のローカル参照フレームでの指定された結果オブジェクトに対応するローカル参照を返します。参照を返す必要がない場合は、結果を NULL に設定します。

パラメータの説明

  • env: JNI インターフェイス ポインタ
  • 結果: 解放する必要があるローカル参照

(7) ローカル参照の作成

jobject NewLocalRef(JNIEnv *env,jobject ref);

ref からローカル参照を作成します。ref はグローバル参照またはローカル参照にすることができ、ref が NULL の場合は NULL を返します。

パラメータの説明

  • env: JNI インターフェイス ポインタ
  • ref: ローカル参照またはグローバル参照を試すことができます。

(8)、弱いグローバル参照

弱いグローバル参照は特別な種類のグローバル参照であり、通常のグローバル参照とは異なり、弱いグローバル参照を使用すると、基礎となる Java オブジェクトをガベージ コレクションできます。弱いグローバル参照は、グローバル参照またはローカル参照が使用される場所であればどこにでも適用できます。ガベージ コレクターが実行されると、オブジェクトが弱い参照によってのみ参照されている場合、基になる変数が解放されます。解放されたオブジェクトへの弱いグローバル参照は NULL と等価です。プログラマーは、isSampleObjectを使用して弱い参照を NULL と比較することにより、弱いグローバルが解放されたオブジェクトを参照しているかどうかを確認できます。JNI の弱いグローバル参照は、Java プラットフォーム API で使用できる Java 弱参照の簡易バージョンです。

ネイティブ メソッドの実行中、ガベージ コレクターが動作している可能性があり、弱い参照によって指定されたオブジェクトがいつでも解放される可能性があります。弱いグローバル参照は、グローバル参照が使用されている場所ならどこにでも適用できますが、誤って NULL になる可能性があるため、通常はそうすることはお勧めできません。

IsSampleObject は、弱いグローバル参照が解放されたオブジェクトを指しているかどうかを識別できますが、オブジェクトが検出された直後に解放されることを妨げるものではありません。これは、プログラマがこのメソッドに頼って、後続の JNI 関数呼び出しで弱いグローバル参照を使用できるかどうかを識別できないことを意味します。

上記の問題を解決したい場合は、JNI 関数 NewLocalRef または NewGlobalRef を使用して、標準のグローバル参照またはローカル参照を使用して同じオブジェクトを指すことをお勧めします。排他が解放されている場合、これらの関数は NULL を返します。それ以外の場合は、(オブジェクトが解放されないように) 強参照が返されます。このオブジェクトへのアクセスが必要なくなった場合は、新しい参照を明示的に削除する必要があります。

1. グローバル弱参照を作成する

jweak NewWeakGlobalRef(JNIEnv *env,jobject obj);

新しい弱いグローバル参照を作成します。obj が NULL を指している場合は NULL を返します。VM メモリがオーバーフローすると、例外 OutOfMemoryError がスローされます。

パラメータの説明

  • env: JNI インターフェイス ポインタ
  • obj: 参照オブジェクト

戻る:

  • グローバル弱参照

2. グローバル弱参照を削除します。

void DeleteWeakGlobalRef(JNIEnv *env,jweak obj);

VM は、指定された弱いグローバル参照に従って、対応するリソースを削除します。

パラメータの説明

  • env: JNI インターフェイス ポインタ
  • obj: 削除される弱いグローバル参照

6、オブジェクト操作

(1) Javaオブジェクトを直接作成する

jobject AllocObject(JNIEnv *env,jclass clazz);

コンストラクターに頼らずに新しい Java オブジェクトを割り当て、オブジェクトへの参照を返します。

パラメータの説明:

  • env: JNI インターフェイス ポインタ
  • clazz:: Java クラス オブジェクト

戻る:

  • Java オブジェクトを返すか、オブジェクトを作成できなかった場合は NULL を返します。

異常な:

  • クラスがインターフェイスまたは抽象クラスの場合、InstantiationException がスローされます。
  • メモリ不足の場合は OutOfMemoryError がスローされます

(2) コンストラクタに従ってJavaオブジェクトを作成する

jobject NewObject(JNIEnv *env,jclass clazz,jmethodID methodID,...);
jobject NewObjectA(JNIEnv *env,jclass clazz,jmethodID methodID,const jvalue *args);
jobject NewObjectV(JNIEnv *env,jclass clazz,jmethodID methodID,va_list args);

新しい Java オブジェクトを構築します。methodID は、コンストラクターを呼び出す必要があることを示します。この ID は GetMethodID() を呼び出して取得する必要があります。GetMethodID() は関数名、void (V) は戻り値です。clazz パラメータは配列クラスを指すことはできません。

  • NewObject: すべてのコンストラクターの入力パラメーターをパラメーター methodID の後に置く必要があります。NewObject() はこれらのパラメータを受け取り、呼び出す必要がある Java コンストラクタに渡します。
  • NewObjectA:methodID の後に、タイプ jvalue-args のパラメーター配列が配置され、コンストラクターに渡す必要があるすべてのパラメーターが格納されます。NewObjectA() は、この配列内のすべてのパラメータを受け取り、それらを呼び出す必要のある Java メソッドに順番に渡します。
  • NewObjectV:methodID の後に、va_list 型の引数が配置され、パラメーターにはコンストラクターに渡す必要があるすべてのパラメーターが格納されます。NewObjectv() はすべてのパラメータを受け取り、それらを呼び出す必要のある Java メソッドに順番に渡します。

パラメータの説明:

  • env: JNI インターフェイス ポインタ
  • clazz::Java クラス
  • MethodID: コンストラクターのメソッド ID

追加パラメータ:

  • NewObject の追加パラメータ: 引数はコンストラクタのパラメータです
  • NewObjectA の追加パラメーター: args はコンストラクターのパラメーターの配列です。
  • NewObjectV の追加パラメーター: args はコンストラクターのパラメーター リストです。

戻る:

  • Java オブジェクト、またはオブジェクトを作成できなかった場合は NULL

異常な:

  • 受信クラスがインターフェースまたは抽象クラスの場合、InstantiationException がスローされます。
  • メモリ不足の場合は OutOfMemoryError をスローします
  • すべての例外はコンストラクターを通じてスローされます

(3) オブジェクトの「クラス」を取得する

jclass GetObjectClass(JNIEnv *env,object obj);

objに対応するクラスを返します。

パラメータの説明

  • env: JNI インターフェイス ポインタ
  • obj: Java オブジェクト。NULL にすることはできません

戻る:

  • Javaの「クラス」オブジェクトを返します。

(4) オブジェクトの「型」を取得する

jobjectRefType GetObjectRefType(JNIEnv *env,jobject obj);

obj パラメータが指すオブジェクトのタイプを返します。パラメータ obj には、ローカル変数、グローバル変数、またはグローバル参照を指定できます。

パラメータの説明

  • env: JNI インターフェイス ポインタ
  • obj: ローカル、グローバル、または弱いグローバル参照

戻る:

  • JNIInvalidRefType=0: obj パラメータが有効な参照型ではないことを示します
  • JNILocalRefType=1: obj パラメータがローカル変数タイプであることを示します
  • JNIGlobalRefType=2: obj パラメータがグローバル変数タイプであることを示します
  • JNIWeakGlobalRefType=3: obj パラメータが弱いグローバル有効参照であることを示します

無効な引用とは、引用のない引用です。つまり、obj のポインタは、関数が作成されたとき、または JNI 関数から返されたときのメモリ内のアドレスを指していません。したがって、NULL は無効な参照です。GetObjectRefType(env, NULL) は JNIInvalidRefType の型を返します。ただし、null 参照が返すのは JNIInvalidRefType ではなく、作成時の参照型です。

PS: 参照の削除中はこの関数を呼び出すことはできません

(5) オブジェクトが「クラス」のサブクラスであるかどうかを判断する

jboolean IsInstanceOf(JNIEnv *env, jobject obj,jclass clazz); 

obj が clazz のインスタンスであるかどうかをテストします。

パラメータ:

  • env: JNI インターフェイス ポインタ
  • obj: Java オブジェクト
  • clazz: Java クラス

戻る:

obj が clazz のインスタンスの場合は JNI_TRUE を返し、それ以外の場合は JNI_FALSE を返します。空のオブジェクトは任意のクラスのインスタンスにすることができます。

(6) 2 つの参照が同じ参照を指しているかどうかを判断します。

jboolean IsSampleObject(JNIEnv *env,jobject ref1,jobject ref2);

2 つの参照が同じオブジェクトを指しているかどうかを判断します。

パラメータの説明:

  • env: JNI インターフェイス ポインタ
  • ref1: Java オブジェクト
  • ref2: Java オブジェクト

戻る:

  • 同じクラス オブジェクトの場合は JNI_TRUE を返し、それ以外の場合は JNI_FALSE を返します。

(7)、属性 ID を返します。

jfieldID GetFieldID(JNIEnv *env,jclass clazz,const char *name,const char *sig);

クラスの非静的属性 ID を取得します。対応する属性は、メソッドの属性名と属性の署名 (つまり、属性の型) によって決まります。この属性 ID を取得することで、一般的に使用される get メソッドと set メソッドである Get <type>Field および Set <type>Field を呼び出すことができます。

パラメータの説明:

  • env: JNI インターフェイス ポインタ
  • clazz: Java クラス オブジェクト
  • name: 「0」で終わる属性名、文字種は「utf-8」
  • sig: 属性署名は「0」で終わり、文字タイプは「utf-8」です

戻る

  • 属性は ID に対応し、操作が失敗した場合は NULL を返します。

異常な:

  • 指定されたプロパティが見つからない場合は NoSuchFieldError をスローします
  • クラスの初期化が失敗した場合は、ExceptionInitializerError がスローされます
  • メモリ不足の場合は OutOfMemoryError をスローします

PS: GetFieldID() を使用すると、初期化されていないクラスの初期化が開始される可能性があります。同時に、GetFieldID() を使用して配列の長さを取得することはできませんが、GetArrayLength() を使用する必要があります。

(8)、属性 ID シリーズを返します。

NativeType GetField(JNIEnv *env,jobject obj,jfieldID fielD);

次のように、クラスの非静的プロパティの値 (一連の関数の略記) を返します。

jobject        GetObjectField(JNIEnv *env,jobject obj,jfieldID fielD)   
jboolean     GetBooleanField(JNIEnv *env,jobject obj,jfieldID fielD)
jbyte           GetByteField(JNIEnv *env,jobject obj,jfieldID fielD)
jchar           GetCharField(JNIEnv *env,jobject obj,jfieldID fielD)
jshort          GetShortField(JNIEnv *env,jobject obj,jfieldID fielD)
jint              GetIntField(JNIEnv *env,jobject obj,jfieldID fielD)
jlong           GetLongField(JNIEnv *env,jobject obj,jfieldID fielD)
jfloat           GetFloatField(JNIEnv *env,jobject obj,jfieldID fielD)
jdouble       GetDoubleField(JNIEnv *env,jobject obj,jfieldID fielD)

パラメータの説明:

  • env: JNI インターフェイス ポインタ
  • obj: Java オブジェクト、空にすることはできません
  • fieldID: 有効なフィールドID

戻る:

  • 対応する属性の値

(9)、属性IDシリーズを設定します

void Set<type>Field(JNIEnv *env,jobject obj,jfieldID fieldID,NativeType value)

クラスの非静的プロパティの値を設定します。このうち、どの属性が GetFieldID() によって決定されます。これは、次のような一連の関数の短縮形です。

void SetObjectField(jobject)

void SetBooleanField(jboolean)

void SetByteField(jbyte)

void SetCharField(jchar)

void SetShortField(jshort)

void SetIntField(jint)

void SetLongField(jlong)

void SetFloatField(jfloat)

void SetDoubleField(jdouble)

パラメータの説明:

  • env: JNI インターフェイス ポインタ
  • obj: Java オブジェクト、空にすることはできません
  • fieldID: 有効なフィールド ID
  • value: 属性の新しい値

(10)、クラスのメソッドIDを取得します。

jmethodID GetMethodID(JNIEnv *env,jclass clazz,const char*name,const char* sig);

クラスまたはインターフェイスのメソッド ID を返します。これは、clazz の親クラスで定義して、clazz によって継承できます。メソッドは名前と署名に基づいて識別されます。

GetMethodID() により、初期化されていないクラスが初期化されます。
コンストラクターの ID を取得する場合は、メソッド名として init を指定し、戻り値の型として void (V) を指定します。

パラメータの説明:

  • env: JNI インターフェイス ポインタ
  • clazz: Java クラス オブジェクト
  • name: 0で終わるメソッド名「utf-8」の文字列
  • sig: 0 で終わる「utf-8」の文字列であるメソッド シグネチャ

戻る:

  • メソッド ID を返します。指定されたメソッドが見つからない場合は、NULL を返します。

異常な:

  • 指定されたメソッドが見つからない場合は、NoSuchMethodError がスローされます
  • 初期化が失敗した場合は、ExceptionInInitializerError がスローされます
  • 十分なメモリがない場合は、OutOfMemoryError がスローされます

(11)、Java インスタンスの非静的メソッド「シリーズ」を呼び出します。

NativeType Call<type>Method(JNIEnv *env,jobject obj,jmethodID methodID,...);
NativeType Call<type>MethodA(JNIEnv *env,jobjct obj,jmethodID methodID ,const jvalue *args);
NativeType  Call<type>MethodV(JNEnv *env,jobject obj,jmethodID methodID,va_list args); 

これらの列はすべて、Java オブジェクトの非静的メソッドをネイティブで呼び出しています。これらの列の違いは、パラメーターを渡す方法が異なることです。メソッドIDにより、対応するJavaオブジェクトの特定のメソッドを特定します。MethodID パラメータは、GetMethodID() を呼び出して取得する必要があります。

「プライベート」関数またはコンストラクターを呼び出す必要がある場合、methodID は親クラスのメソッドではなく、obj クラスのメソッドである必要があります。

それらの違いを見てみましょう

  • CallMethod: メソッドの入力パラメータをパラメータmethodIDの後に置く必要があります。CallMethod() は実際にこれらのパラメータを、呼び出す必要がある Java メソッドに渡します。
  • CallMethodA: MethodID の背後には、コンストラクターに渡す必要があるすべてのパラメーターを格納する jvalue 型の args 配列があります。CallMethodA() は、この配列内のパラメータを受け取り、それらを対応する Java メソッドに順番に渡します。
  • CallMethodV:methodID の背後には、Wieva_list 型のパラメーター args があり、コンストラクターに渡す必要があるすべてのパラメーターが格納されます。CallMethodV() はすべてのパラメータを受け取り、それらを呼び出す必要のある Java メソッドに順番に渡します。
Call<type>Method Routine Name            Native Type

CallVoidMethod() 
CallVoidMethodA()                        void
CallVoidMethodV()                       

CallObjectMethod()
CallObjectMethodA()                      jobject
CallObjectMethodV()

CallBooleanMethod()
CallBooleanMethodA()                     jboolean
CallBooleanMethodV()

CallByteMethod()
CallByteMethodA()                        jbyte
CallByteMethodV()

CallCharMethod()
CallCharMethodA()                        jchar
CallCharMethodV()

CallShortMethod() 
CallShortMethodA()                       jshort
CallShortMethodV()

CallIntMethod()
CallIntMethodA()                         jint
CallIntMethodV()

CallLongMethod()
CallLongMethodA()
CallLongMethodV()

CallFloatMethod()
CallFloatMethodA()                        jlong
CallFloatMethodV()

CallDoubleMethod()
CallDoubleMethodA()                      jfloat
CallDoubleMethodV()

パラメータの説明:

  • env: JNI インターフェイス ポインタ
  • obj: 対応する Java オブジェクト
  • MethodID: メソッドのメソッドID

戻る:

  • Javaメソッドの呼び出しに対応する結果を返します。

異常な:

  • Java メソッドの実行中に例外が発生します。

(12)、クラスの非抽象メソッドの呼び出し

次のように、親クラスでインスタンス メソッドを呼び出します。

CallNonvirtual<type>Method 
CallNonvirtual<type>MethodA 
CallNonvirtual<type>MethodV 

詳細は次のとおりです。

NativeType CallNonvirtual<Type>Method(JNIEnv *env,jobject obj,jclass clazz,jmethodID methodID,....);
NativeType CallNonvirtual<Type>MethodA(JNIEnv *env,jobject obj,jclass clazz,jmethodID methodID,const jvalue *args);
NativeType CallNonvirtual<type>MethodV(JNIEnv *env, jobject obj,
jclass clazz, jmethodID methodID, va_list args);

この一連の操作は、特定のクラスとそのメソッドIDに応じてJavaオブジェクトのインスタンスの非静的メソッドを呼び出すもので、GetMethodID()を呼び出してmethodIDパラメータを取得する必要があります。

CallNonvirtual<Type>Method と Call<type>Method は異なります。CallNonvirtual<Type>Method は「クラス」に基づき、Call<type>Method はクラス オブジェクトに基づきます。したがって、CallNonvirtual<Type>Method の入力パラメータは clazz であり、methodID は親クラスではなく、obi のクラスから取得する必要があります。

それらの違いを見てみましょう

  • CallNonvirtual<type>Method : メソッドの入力パラメータをパラメータmethodIDの後に置く必要があります。CallNonvirtual<type>Method() は、実際には、呼び出す必要がある Java メソッドにこれらのパラメータを渡します。
  • CallNonvirtual<type>Method:methodID の背後には、コンストラクターに渡す必要があるすべてのパラメーターを格納する jvalue 型の args 配列があります。CallNonvirtual<type>Method() は、この配列内のパラメータを受け取り、それらを対応する Java メソッドに順番に渡します。
  • CallNonvirtual<type>MethodV:methodID の背後には、Wieva_list 型のパラメーター引数があり、コンストラクターに渡す必要があるすべてのパラメーターを格納します。CallNonvirtual<type>MethodV() はすべてのパラメータを受け取り、呼び出す必要がある Java メソッドに順番に渡します。

上記の一連のメソッドを次のように展開します。

CallNonvirtual<type>Method Routine Name      Native Type
CallNonvirtualVoidMethod()
CallNonvirtualVoidMethodA()                  void
CallNonvirtualVoidMethodV()

CallNonvirtualObjectMethod()
CallNonvirtualObjectMethodA()                jobject
CallNonvirtualObjectMethodV()

CallNonvirtualBooleanMethod()
CallNonvirtualBooleanMethodA()               jboolean
CallNonvirtualBooleanMethodV()

CallNonvirtualByteMethod()
CallNonvirtualByteMethodA()                  jbyte
CallNonvirtualByteMethodV()

CallNonvirtualCharMethod()
CallNonvirtualCharMethodA()                  jchar
CallNonvirtualCharMethodV()

CallNonvirtualShortMethod()
CallNonvirtualShortMethodA()                 jshort
CallNonvirtualShortMethodV()

CallNonvirtualIntMethod()
CallNonvirtualIntMethodA()                   jint
CallNonvirtualIntMethodV()

CallNonvirtualLongMethod()
CallNonvirtualLongMethodA()                  jlong
CallNonvirtualLongMethodV()

CallNonvirtualFloatMethod()
CallNonvirtualFloatMethodA()                 jfloat
CallNonvirtualFloatMethodV()

CallNonvirtualDoubleMethod()
CallNonvirtualDoubleMethodA()                jdouble
CallNonvirtualDoubleMethodV()

パラメータの説明:

  • env: JNI インターフェイス ポインタ
  • obj: Java オブジェクト
  • clazz: Java クラス
  • methodID:方法ID

戻る:

  • Javaメソッドを呼び出した結果

例外をスローします。

  • Javaメソッドの実行中に発生する可能性のある例外

(13)、静的属性を取得します

jfieldID GetStaticFieldID(JNIEnv *env,jclass clazz,const char* name,const char *sig);

クラスの静的属性 ID を取得し、属性名とラベルに基づいてそれがどの属性であるかを判断します。GetStaticField() および SetStaticField() は、プロパティ ID を使用してプロパティを操作します。クラスが初期化されていない場合、GetStaticFieldID() を直接呼び出すとクラスが初期化されます。

パラメータの説明:

  • env: JNI インターフェイス ポインタ
  • clazz: Java クラス
  • name: 静的属性の属性名。「utf-8」でエンコードされ、0 で終わる文字列です。
  • sig: 属性の署名。「utf-8」でエンコードされ、0 で終わる文字列です。

戻る:

静的属性 ID を返します。指定された静的属性が見つからない場合は NULL を返します。

異常な:

  • 指定された静的プロパティが見つからない場合は、NoSuchFieldError をスローします
  • クラスの初期化に失敗すると、ExceptionInInitializerError がスローされます
  • 十分なメモリがない場合は、OutOfMemoryError がスローされます

(14)、静的属性シリーズを取得

NativeType GetStatic<type>Field(JNIEnv *env,jclass clazz,jfieldID fieldID);

このシリーズは、オブジェクトの静的プロパティの値を返します。静的属性の ID は GetStaticFieldID() で取得でき、この ID を使用してこれを取得して操作できます。

関数名と関数の戻り値を以下に示します。そのため、GetStatic<type>Field のクラスをフィールドの Java 型またはテーブル内の実際の静的フィールド アクセサーに置き換えるだけで済みます。そして、NativeType を対応するネイティブ タイプに置き換えます。

GetStatic<type>Field Routine Name      Native Type
GetStaticObjectField()                 jobject
GetStaticBooleanField()                jboolean
GetStaticByteField()                   jbyte
GetStaticCharField()                   jchar
GetStaticShortField()                  jshort
GetStaticIntField()                    jint
GetStaticLongField()                   jlong
GetStaticFloatField()                  jfloat
GetStaticDoubleField()                 jdouble

パラメータの説明:

  • env: JNI インターフェイス ポインタ
  • clazz: Java クラス
  • フィールド: 静的属性 ID

戻る:

  • 静的プロパティを返す

(15)、静的属性シリーズを設定します

void SetStatic<type>Field(JNIEnv *env,jclass clazz,jfieldID fieldID,NativeType value);

このシリーズはクラスの静的プロパティの値を設定します。静的フィールドの ID は、GetStaticFieldID() を通じて取得できます。

関数名とその値については、以下で詳しく説明します。Java では、SetStatic<type> と渡された NativeType を通じて静的プロパティを設定できます。

SetStatic<type>Field Routine Name         NativeType
SetStaticObjectField()                    jobject
SetStaticBooleanField()                   jboolean
SetStaticByteField()                      jbyte
SetStaticCharField()                      jchar
SetStaticShortField()                     jshort
SetStaticIntField()                       jint
SetStaticLongField()                      jlong
SetStaticFloatField()                     jfloat
SetStaticDoubleField()                    jdouble

パラメータの説明:

  • env: JNI インターフェイス ポインタ
  • clazz: Java クラス
  • フィールド: 静的属性 ID
  • 値: 設定値

(16)、静的関数IDを取得

jmethodID GetStaticMethodID(JNIEnv *env,jclass clazz,const char *name,const char sig);

クラスの静的メソッド ID を返します。このメソッドはメソッド名とシグネチャによって識別されます。クラスが初期化されていない場合、GetStaticMethodID() を呼び出すとクラスが初期化されます。

パラメータの説明:

  • env: JNI インターフェイス ポインタ
  • clazz: Java クラス
  • name: 静的メソッドのメソッド名。「utf-8」でエンコードされ、0 で終了します。
  • sig: 「utf-8」でエンコードされたメソッドのシグネチャ、および 0 で終わる文字列

戻る:

  • メソッド ID を返すか、操作が失敗した場合は NULL を返します。

異常な:

  • 対応する静的メソッドが見つからない場合は、NoSuchMethodError がスローされます
  • クラスの初期化が失敗した場合は、ExceptionInInitializerError がスローされます
  • システムのメモリが不足している場合は OutOfMemoryError をスローします

(17)、静的関数シリーズの呼び出し

NativeType CallStatic<type>Method(JNIEnv *env,jclass clazz,jmethodID methodID,...);
NativeType CallStatic<type>MethodA(JNIEnv *env,jclass clazz,jmethodID methodID,... jvalue *args);
NativeType CallStatic<type>MethodV(JNIEnv *env,jclass,jmethodID methodid, va_list args)

指定したメソッドIDに応じて、Javaオブジェクトの静的メソッドを操作できます。MethodID は GetStaticMethodID() を通じて取得できます。メソッドの ID は、親クラスのメソッド ID ではなく、clazz のものである必要があります。

詳細な方法は次のとおりです。

CallStatic<type>Method Routine Name                Native Type
CallStaticVoidMethod()
CallStaticVoidMethodA()                            void
CallStaticVoidMethodV()

CallStaticObjectMethod()
CallStaticObjectMethodA()                          jobject
CallStaticObjectMethodV()

CallStaticBooleanMethod()
CallStaticBooleanMethodA()                         jboolean
CallStaticBooleanMethodV()

CallStaticByteMethod()
CallStaticByteMethodA()                            jbyte
CallStaticByteMethodV()

CallStaticCharMethod()
CallStaticCharMethodA()                            jchar
CallStaticCharMethodV()

CallStaticShortMethod()
CallStaticShortMethodA()                           jshort
CallStaticShortMethodV()

CallStaticIntMethod()
CallStaticIntMethodA()                             jint
CallStaticIntMethodV()

CallStaticLongMethod()
CallStaticLongMethodA()                            jlong
CallStaticLongMethodV()

CallStaticFloatMethod()
CallStaticFloatMethodA()                           jfloat
CallStaticFloatMethodV()

CallStaticDoubleMethod()
CallStaticDoubleMethodA()                          jdouble
CallStaticDoubleMethodV()

パラメータの説明:

  • env: JNI インターフェイス ポインタ
  • clazz: Java クラス
  • MethodID: 静的メソッドID

戻る:

  • 静的Javaメソッドの呼び出しメソッドを返します。

異常な:

  • Javaメソッドの実行中にスローされた例外

7、文字列操作

(1)、文字列を作成します

jstring NewString(JNIEnv *env,const jchar *unicodeChars,jszie len);

パラメータの説明:

  • env: JNI インターフェイス ポインタ
  • unicodeChars: Unicode 文字列へのポインタ
  • len: Unicode 文字列の長さ

戻る:

  • Java 文字列オブジェクトを返します。文字列を作成できない場合は NULL を返します。

異常な:

  • メモリ不足の場合は OutOfMemoryError をスローします

(2) 文字列の長さを取得する

jsize  GetStringLength(JNIEnv *env,jstring string);

Java 文字列の長さ (Unicode 文字の数) を返します。

パラメータの説明:

  • env: JNI インターフェイス ポインタ
  • 文字列: Java 文字列オブジェクト

戻る:

  • Java文字列の長さを返します。

(3) 文字列のポインタを取得する

const jchar* GetStringChar(JNIEnv *env,jstring string , jboolean *isCopy);

文字列の UNICODE 文字配列へのポインタを返します。このポインタは、ReleaseStringchars() 関数が呼び出されるまで有効です。

isCopy が null 以外の場合は、コピーの完了後に isCopy を JNI_TRUE に設定します。レプリケーションがない場合は、JNI_FALSE に設定します。

パラメータの説明:

  • env: JNI インターフェイス ポインタ
  • 文字列: Java 文字列オブジェクト
  • isCopy: ブール値へのポインタ

戻る:

  • Unicode 文字列へのポインタを返すか、操作が失敗した場合は NULL を返します。

(4)、紐を放します

void ReleaseStringChars(JNIEnv *env,jstring string,const jchar *chars);

VM を介して、ネイティブ コードは文字にアクセスできなくなります。パラメータ chars はポインタです。これは、GetStringChars() 関数を通じて取得できます。

パラメータの説明:

  • env: JNI インターフェイス ポインタ
  • 文字列: Java 文字列オブジェクト
  • chars: Unicode文字列へのポインタ

(5) UTF-8文字列を作成する

jstring NewStringUTF(JNIEnv *env,const char *bytes);

UTF-8文字列を作成します。

パラメータの説明:

  • env: JNI インターフェイス ポインタ
  • バイト: UTF-8 文字列へのポインタ

戻る:

  • Java String オブジェクト、または文字列を構築できなかった場合は NULL。

異常な:

  • システムのメモリが不足している場合は OutOfMemoryError をスローします

(6) UTF-8文字列の長さを取得する

jsize GetStringUTFLength(JNIEnv *env,jstring string);

文字列の UTF-8 の長さをバイト単位で返します。

パラメータの説明:

  • env: JNI インターフェイス ポインタ
  • 文字列: Java 文字列オブジェクト

戻る:

  • 文字列の UTF-8 の長さ

(7)、StringUTFCharsのポインタを取得

const char *GetStringUFTChars(JNIEnv *env, jString string, jboolean *isCopy);

UTF-8 文字配列へのポインターを返します。この配列は、ReleaseStringUTFChars() 関数呼び出しによって解放されない限り有効です。

isCopy が NULL でない場合、割り当ての完了後、*isCopy は JNI_TRUE に設定されます。コピーしない場合は、JNI_FALSE に設定します。

パラメータの説明:

  • env: JNI インターフェイス ポインタ
  • 文字列: Java 文字列オブジェクト
  • isCopy: ブール値へのポインタ

戻る:

  • UTF-8 文字列へのポインタ、または操作が失敗した場合は NULL。

(8)、UTFCharsを解放します

void ReleaseStringUTFChars(JNIEnv *env,jstring string,const char *urf)

仮想マシンを介して、ネイティブ コードは utf にアクセスしなくなります。utf はポインターであり、GetStringUTFChars() を呼び出すことで取得できます。

パラメータの説明:

  • env: JNI インターフェイス ポインタ
  • 文字列: Java 文字列オブジェクト
  • utf: utf-8 文字列へのポインタ

注: JDK/JRE 1.1 では、プログラマはユーザー指定のバッファーでプリミティブ型の配列要素を取得できます。JDK/JRE1.2 以降、Unicode 文字 (UTF -16 エンコーディング) または UTF-8 文字を許可する追加のメソッドが提供されます。これらの方法は次のとおりです。

(9)、JRE1.2の新しい文字列操作方法

1. 文字列をインターセプトする

void GetStringRegion(JNIEnv *env,jstring str,jsize start,jsize len,jchar *buf)

str (Unicode 文字) の開始位置から len の長さを切り出し、buf に配置します。範囲外の場合は StringIndexOutOfBoundsException をスローします。

2. 文字列をインターセプトし、UTF-8 形式に変換します。

void GetStringUTFRegion(JNIEnv *env,jstring str,jsize start ,jsize len,char *buf);

str(Unicode文字列)を開始位置からlenの長さでインターセプトし、UTF-8エンコードに変換してbufに格納します。

3. 文字列をインターセプトし、UTF-8 形式に変換します。

const jchar * GetStringCritical(JNIEnv *env,jstring string,jboolean *isCopy);
void ReleaseStringCritical(JNIEnv *env,jstring string,cost jchar * carray);

上記の 2 つの関数は、GetStringChars() 関数と ReleaseStringChars() 関数に似ています。仮想マシンは、可能であれば文字列要素へのポインタを返し、それ以外の場合はコピーされたコピーを返します。

GetStringChars () と ReleaseStringChars () これら 2 つの関数には大きな制限があります。これら 2 つの関数を使用する場合、これら 2 つの関数間のコードは、スレッドをブロックしたり、JVM の他のスレッドを待機させたりするネイティブ関数や JNI 関数を呼び出すことはできません。これらの制限により、ネイティブ メソッドが GetStringCritical から取得した文字列へのポインターを保持している場合、JVM は GC を無効にすることができます。GC が無効になると、GC を開始するスレッドはブロックされます。ただし、2 つの関数 GetStringChars() と ReleaseStringChars() の間のネイティブ コードは、ブロッキングを引き起こす呼び出しを実行したり、新しいオブジェクトに JVM でメモリを割り当てたりすることはできません。そうしないと、JVM がデッドロックする可能性があります。次のシナリオを想像してください。

  1. 現在のスレッドによってトリガーされた GC がブロックを終了して GC を解放した場合にのみ、他のスレッドによって開始された GC はブロックから解放され、実行を継続できます。
  2. このプロセス中、現在のスレッドは常にブロックされます。これは、他のスレッドが GC を待機している間に、ブロッキング呼び出しは他のスレッドによって保持されているロックを取得する必要があるためです。

GetStringChars() と ReleaseStringChars() の交互の反復呼び出しは安全ですが、その場合、それらの使用は厳密に順序付けされる必要があります。さらに、メモリオーバーフローにより戻り値が NULL になるかどうかを忘れずに確認する必要があります。JVM は GetStringChars() 関数の実行時にデータをコピーする可能性がまだあるため、特に JVM によってメモリに格納された配列が不連続である場合、連続したメモリ空間へのポインタを返すために、JVM はすべてのデータをコピーする必要があります。

要約すると、デッドロックを回避するには、GetStringChars() と ReleaseStringChars() の間で JNI 関数を呼び出さないでください。

8、配列演算

(1) 配列の長さを取得する

jsize GetArrayLength(JNIEnv *env,jarray array)

配列の長さを返します。

パラメータの説明:

  • env: JNI インターフェイス ポインタ
  • 配列: Java 配列

戻る:

  • 配列の長さ

(2) オブジェクトの配列を作成する

jobjectArray NewObjectArray(JNIEnv *env,jsize length,jclass elementClass, jobject initialElement);

要素が elementClass 型で、デフォルト値がinitialElementであるオブジェクトの新しい配列を作成します。

パラメータの説明:

  • env: JNI インターフェイス ポインタ
  • 長さ: 配列サイズ
  • elementClass: 配列要素クラス
  • InitialElement: 配列要素の初期値

戻る:

  • Java 配列オブジェクト、または配列を構築できない場合は NULL

異常な:

  • メモリ不足の場合は OutOfMemoryError をスローします

(3) 配列要素内の要素を取得する

jobject GetObjectArrayElement(JNIEnv *env,jobjectArray array,jsize index);

要素内の位置にある要素を返します。

パラメータの説明:

  • env: JNI インターフェイス ポインタ
  • 配列: Java 配列
  • インデックス: 配列の添字

戻る:

  • Javaオブジェクト

異常な:

  • インデックスの添字が有効な添字ではない場合、ArrayIndexOutOfBoundsException がスローされます。

(4)、配列内の要素の値を設定します

void SetObjectArrayElement(JNIEnv *env,jobjectArray array,jsize index,jobject value);

添え字をインデックス要素の値に設定します。

パラメータの説明:

  • env: JNI インターフェイス ポインタ
  • 配列: Java 配列
  • インデックス: 配列の添字
  • value: 配列要素の新しい値

異常な:

  • インデックスが有効な添字ではない場合、ArrayIndexOutOfBoundsException がスローされます。
  • value が要素クラスのサブクラスではない場合、ArrayStoreException がスローされます。

(5) 一連の基本型配列を作成する

ArrayType New<PrimitiveType>Array(JNIEnv *env,jsize length);

プリミティブ型の配列オブジェクトを構築するための一連の操作。特定のプリミティブ型の配列の作成関数については、以下で説明します。New<PrimitiveType>Array を実際のプリミティブ型配列作成関数に置き換えてから、ArrayType を対応する配列型に置き換えることができます。

New<PrimitiveType>Array Routines           Array Type
NewBooleanArray()                          jbooleanArray
NewByteArray()                             jbyteArray
NewCharArray()                             jcharArray
NewShortArray()                            jshortArray
NewIntArray()                              jintArray
NewLongArray()                             jlongArray
NewFloatArray()                            jfloatArray
NewDoubleArray()                           jdoubleArray

パラメータの説明:

  • env: JNI インターフェイス ポインタ
  • 長さ: 配列の長さ

戻る:

  • Java 配列、または配列を作成できなかった場合は NULL。

(6) 基本型配列の中配列ポインタ系列を取得

NativeType * Get<PrimitiveType>ArrayElements(JNIEnv *env,ArrayType array,jboolean * isCopy);

プリミティブ型の配列本体を返す関数のセット。結果は、対応する Release<PrimitiveType>ArrayElements() 関数が呼び出されるまで有効です。返される配列は Java 配列のコピーである可能性があるため、Release<PrimitiveType>ArrayElements() 関数が呼び出されるまで、返される配列への変更をプリミティブ配列に反映する必要はありません。

isCopy が NULL でない場合、コピーの完了後に *isCopy は JNI_TRUE に設定されます。コピーしない場合は、JNI_FALSE に設定します。

特定のプリミティブ型の配列要素に対する特定の関数を以下に説明します。

  • テーブル内の Get<PrimitiveType>ArrayElements を実際のプリミティブ> タイプの関数に置き換えます。
  • ArrayType を対応する配列型に置き換えます。
  • NativeType をローカル変数に置き換えます

Java 仮想マシンでブール配列が常にどのように表されるかに関係なく、GetBooleanArrayElements() は常に jboolean 型のポインターを返します。ここで、各バイトは要素 (オープン パッケージ表現) を表します。他のすべての型の配列は、メモリ内で連続していることが保証されます。

Get<PrimitiveType>ArrayElements Routines     Array Type         Native Type
GetBooleanArrayElements()                    jbooleanArray      jboolean
GetByteArrayElements()                       jbyteArray         jbyte
GetCharArrayElements()                       jcharArray         jchar
GetShortArrayElements()                      jshortArray        jshort
GetIntArrayElements()                        jintArray          jint
GetLongArrayElements()                       jlongArray         jlong
GetFloatArrayElements()                      jfloatArray        jfloat
GetDoubleArrayElements()                     jdoubleArray       jdouble

パラメータの説明:

  • env: JNI インターフェイス ポインタ
  • 配列: Java 配列
  • isCopy: ブール値へのポインタ

戻る:

  • 配列の要素へのポインタを返します。操作が失敗した場合は NULL を返します。

(7) 基本型の配列シリーズをリリース

void Release<PrimitiveType>ArrayElements(JNIEnv *env,ArrayType array,NativeType *elems,jint mode);

ネイティブが配列の要素にアクセスしなくなったことを仮想マシンに通知します。elems パラメーターは、対応する Get<PrimitiveType> ArrayElements() 関数の配列要素によって返されるポインターです。この関数は、必要に応じて、要素上のすべての変換を元の配列要素にコピーします。mode パラメータは、配列バッファを解放する方法を指定します。elems が配列のコピーでない場合、mode は効果がありません。

mode の値には次の 3 つの状況があります。

  • 0: コンテンツをコピーし、要素バッファを解放します。
  • JNI_COMMIT: コンテンツをコピーしますが、要素バッファは解放しません
  • JNI_ABORT: 変更の可能性をコピーせずにバッファを解放します

ほとんどの場合、プログラマは引数として「0」を渡します。これは、配列の固定とコピーの一貫した動作を保証するためです。他のオプションにより、プログラマはメモリをより詳細に制御できます。

特定のプリミティブ型の配列要素に対する特定の関数を以下に説明します。

  • Release <PrimitiveType> ArrayElements を以下の実際の primitive> タイプ関数の 1 つに置き換えます。
  • ArrayType を対応する基本配列型に置き換えます。
  • NativeType をローカル変数に置き換えます

プリミティブ型の配列の解放の詳細については、以下で説明します。次のように置き換える必要があります。

Release<PrimitiveType>ArrayElements Routines     Array Type               Native Type
ReleaseBooleanArrayElements()                    jbooleanArray            jboolean
ReleaseByteArrayElements()                       jbyteArray               jbyte
ReleaseCharArrayElements()                       jcharArray               jchar
ReleaseShortArrayElements()                      jshortArray              jshort
ReleaseIntArrayElements()                        jintArray                jint
ReleaseLongArrayElements()                       jlongArray               jlong
ReleaseFloatArrayElements()                      jfloatArray              jfloat
ReleaseDoubleArrayElements()                     jdoubleArray             jdouble

パラメータの説明:

  • env: JNI インターフェイス ポインタ
  • 配列: Java 配列
  • elems: プリミティブ型の配列へのポインタ
  • モード: リリースモード

(8)、過去の基本型の配列系列をコピー

void Get<PrimitiveType> ArrayRegion(JNIEnv *env,ArrayType array,jsize start,jsize len,NativeType *buf);

プリミティブ型の配列を buff にコピーします

特定のプリミティブ型の配列要素に対する特定の関数を以下に説明します。

  • Get<PrimitiveType> ArrayRegion を、以下の実際の primitive> タイプの関数の 1 つに置き換えます。
  • ArrayType を対応する基本配列型に置き換えます。
  • NativeType をローカル変数に置き換えます
Get<PrimitiveType>ArrayRegion Routine           Array Type              Native Type
GetBooleanArrayRegion()                         jbooleanArray           jboolean
GetByteArrayRegion()                            jbyteArray              jbyte
GetCharArrayRegion()                            jcharArray              jchar
GetShortArrayRegion()                           jshortArray             jhort
GetIntArrayRegion()                             jintArray               jint
GetLongArrayRegion()                            jlongArray              jlong
GetFloatArrayRegion()                           jfloatArray             jloat
GetDoubleArrayRegion()                          jdoubleArray            jdouble

パラメータの説明:

  • env: JNI インターフェイス ポインタ
  • 配列: Java 配列
  • start: 開始インデックス
  • len: コピーされる長さ
  • buf: ターゲットバッファ

異常な:

  • インデックスが無効な場合は ArrayIndexOutOfBoundsException をスローします

(9)、基本型配列の配列をシリーズにコピーし直します。

void Set<PrimitiveType> ArrayRegion(JNIEnv *env,ArrayType array,jsize start,jsize len,const NativeType *buf);

これは主に、基本型の配列をバッファリングおよびコピーするための関数です。

特定のプリミティブ型の配列要素に対する特定の関数を以下に説明します。

  • Set<PrimitiveType>ArrayRegion を、以下の実際の Basic> タイプ関数の 1 つに置き換えます。
  • ArrayType を対応する基本配列型に置き換えます。
  • NativeType をローカル変数に置き換えます
Set<PrimitiveType>ArrayRegion Routine        Array Type            Native Type
SetBooleanArrayRegion()                      jbooleanArray         jboolean
SetByteArrayRegion()                         jbyteArray            jbyte
SetCharArrayRegion()                         jcharArray            jchar
SetShortArrayRegion()                        jshortArray           jshort
SetIntArrayRegion()                          jintArray             jint
SetLongArrayRegion()                         jlongArray            jlong
SetFloatArrayRegion()                        jfloatArray           jfloat 
SetDoubleArrayRegion()                       jdoubleArray          jdouble

パラメータの説明:

  • env: JNI インターフェイス ポインタ
  • 配列: Java 配列
  • start: 開始インデックス
  • len: コピーされる長さ
  • buf:ソースバッファ

異常な:

  • インデックスが無効な場合は ArrayIndexOutOfBoundsException がスローされます

(10)、補足

JDK/JER 1.1 以降、プリミティブ配列要素へのポインターを取得するための Get/Release<primitivetype>ArrayElements 関数が提供されています。VM がロックをサポートしている場合は元の配列へのポインタを返し、それ以外の場合はコピーを返します。
JDK/JRE 1.3 以降、新機能が導入され、VM がロックをサポートしていない場合でも、ネイティブ コードは配列要素への直接ポインターを取得できます。

void *GetPrimitiveArrayCritical(JNIEnv *env,jarray array,jboolean *isCopy);
void ReleasePrimitiveArrayCritical(JNIEnv *env,jarray array,void *carray,jint mode);

これら 2 つの関数は上記の Get/Release <primitivetype> ArrayElements 関数に非常に似ていますが、この関数を使用する場合には依然として多くの制限があります。

GetPrimitiveArrayCritical を呼び出した後、ReleasePrimitiveArrayCritical を呼び出すまでは、この領域は他の JNI 関数を呼び出すことはできません。また、スレッドをブロックして別の Java スレッドを待機させる可能性のあるシステム コールを呼び出すこともできません。

たとえば、現在のスレッドは、読み取り関数を呼び出して、他のストリームによって書き込まれているストリームを読み取ることはできません。

9 つのシステムレベルの操作

(1) 登録方法

jint RegisterNatives(JNIEnv *env,jclass clazz,const JNINativeMethod *methods,jint nMethod);

ローカル メソッドは clazz パラメータに従って登録され、methods パラメータはローカル メソッドの名前、シグネチャ、および関数ポインタを含む JNINativeMethod 構造体配列を定式化します。このうち、名前とシグネチャはエンコーディング「UTF-8」へのポインタであり、nMethod パラメータは配列内のローカル メソッドの数を示します。

JNINativeMethod 構造体は次のとおりです。

typedef struct { 
char *name; 
char *signature; 
void *fnPtr; 
} JNINativeMethod; 

パラメータの説明:

  • env: JNI インターフェイス ポインタ
  • clazz: Java クラス オブジェクト
  • メソッド: クラス内のネイティブ メソッド
  • nMethod: クラス内のネイティブ メソッドの数

戻る;

  • 成功すると 0 が返され、失敗すると負の数が返されます。

異常な:

  • 指定されたメソッドが見つからない場合、またはメソッドがネイティブ メソッドではない場合は、NoSuchMethodError がスローされます。

(2) キャンセル方法

jint UnregisterNatives(JNIEnv *env,jclass clazz);

ネイティブ メソッドの登録を解除します。このクラスは、以前に関数によって登録されていない状態を再利用します。この関数は通常、ネイティブ コードでは呼び出すことができません。この関数は、特定のプログラムのネイティブ ライブラリを再ロードおよび再リンクするためのメソッドを提供します。

パラメータの説明:

  • JNI: インターフェースポインタ
  • clazz: Java クラス オブジェクト

戻る:

  • ログアウトが成功すると 0 が返され、失敗すると負の数が返されます。

(3) 監視動作

jint MonitorEnter(JNIEnv *env,jobject obj);

obj によって参照される基礎となる Java オブジェクトに関連付けられたモニター。obj 参照を null にすることはできません。すべての Java オブジェクトには、関連付けられたモニターがあります。現在のスレッドに obj に関連付けられたモニターがすでにある場合は、このスレッドがモニターに入った回数を示すモニターのカウンターを追加します。obj に関連付けられたモニターがどのスレッドにも属していない場合、現在のスレッドがモニターの所有者となり、カウンターを 1 に設定します。他のカウンターが既にモニターを所有している場合、現在のスレッドはモニターが取得されるまで待機します。そしてモニターの所有権を取得します。

MonitorEnter JNI 関数を通じて呼び出されたモニターは、monitorexitJVM 命令または同期メソッドでは終了できません。MonitorEnterJNI 関数呼び出しと Monitorenter Java 仮想マシン命令は、同じオブジェクトでモニターに入ろうと競合する可能性があります。

デッドロックを回避するには、JNI モニターを解放するために DetachCurrentThread インターフェースが暗黙的に呼び出されない限り、MonitorEnterJNI 関数呼び出しを通じて入ったモニターは MonitorExitJNI 呼び出しで終了する必要があります。

パラメータの説明:

  • env: JNI インターフェイス ポインタ
  • obj: 通常の Java オブジェクトまたはクラス オブジェクト

戻る:

  • 成功すると 0 が返され、失敗すると負の数が返されます。

(4) モニター終了

jint MonitorExit(JNIEnv *env,jobject obj);

現在のスレッドは、この obj に関連付けられたモニターを所有しており、スレッドはカウンターをデクリメントして、スレッドがモニターに入った回数を示します。カウンタの値が 0 になると、スレッドはモニターを解放します。ネイティブ コードでは、MonitorExit を直接呼び出してモニターを解放することはできません。代わりに、Java 仮想マシン命令を使用して、同期メソッドを通じてモニターを解放します。

パラメータの説明:

  • env: JNI インターフェイス ポインタ
  • obj: 通常の Java オブジェクトまたはクラス オブジェクト

戻る:

  • 成功すると 0 が返され、失敗すると負の数が返されます。

異常な:

  • 現在のスレッドがモニターを所有していない場合は、IllegalMonitorStateException がスローされる必要があります。

10 個の NIO オペレーション

NIO 関連の操作により、ネイティブ コードが java.nio のダイレクト バッファーに直接アクセスできるようになります。ダイレクト バッファの内容は、通常のガベージ コレクタの外部のローカル メモリに存在する場合があります。ダイレクトバッファの詳細については、NIO クラスおよび java.nio.ByteBuffer クラスの仕様を参照してください。

JDK/JRE 1.4 では、ダイレクト バッファの検査と操作を可能にする新しい JNI 関数が導入されました。

  • NewDirectByteBuffer
  • GetDirectBufferAddress
  • GetDirectBufferCapacity

これらの機能をサポートするにはすべての Java 仮想マシン実装が必要ですが、すべての実装がダイレクト バッファへの JNI アクセスをサポートする必要があるわけではありません。JVM がそのようなアクセスをサポートしていない場合、NewDirectByteBuffer 関数と GetDirectBufferAddress 関数は常に NULL を返す必要があり、GetDirectBufferCapacity 関数は常に -1 を返す必要があります。JVM がそのようなアクセスをサポートしている場合は、適切な値を返すためにこれら 3 つの関数を実装する必要があります。

(1) バイトバッファを返す

jobject NewDirectByteBuffer(JNIEnv *env,void *address,jlong capacity);

メモリ アドレス address から始まる直接 java.nio.ByteBuffer メモリ ブロック容量バイトを割り当てて返します。

この関数を呼び出してバイト バッファ オブジェクトを返すネイティブ コードは、バッファが読み書きできる信頼できるメモリ領域を指していることを確認する必要があります。不正なメモリ位置を入力すると、任意の値が返される可能性があり、DNA は目に見えて影響されず、例外がスローされる可能性があります。

パラメータの説明:

  • env: JNIEnv インターフェイス ポインタ
  • address: メモリ領域の開始アドレス
  • 容量: メモリ領域のサイズ

戻る:

新しく開かれた java.nio.ByteBuffer オブジェクトへのローカル参照を返します。例外が発生した場合は NULL を返します。JVM がダイレクト バッファへの JNI アクセスをサポートしていない場合も、NULL を返します。

異常な:

バッファ割り当てに失敗した場合は OutOfMemoryError を返します

(2) ダイレクトバッファ内のオブジェクトの先頭アドレスを返す

void* GetDirectBufferAddress(JNIEnv *env,jobject buf);

java.nio.Buffer の初期メモリ アドレスを取得して返します。

この関数を使用すると、ネイティブ コードがダイレクト バッファ オブジェクトを通じて Java コードと同じメモリ領域にアクセスできるようになります。

パラメータの説明:

  • env: JNIEnv インターフェイス ポインタ
  • バッファ:java.nio.Buffer对オブジェクト

戻る:

メモリ領域の最初のアドレスを返します。メモリ領域が未定義の場合は NULL を返し、指定されたオブジェクトが java.nio.buffer でない場合は NULL を返し、仮想マシンが JNI アクセスをサポートしていない場合は NULL を返します。

(3) ダイレクトバッファ内のオブジェクトのメモリ容量を返す

jlong GetDirectBufferCapacity(JNIEnv *env,jobject buf);

java.nio.Buffer のメモリ容量を取得および返します。容量とは、メモリ領域に保持できる要素の数です。

パラメータ:

  • env: JNIEnv インターフェイス ポインタ
  • バッファ:java.nio.Buffer对オブジェクト

戻る:

メモリ領域の容量を返します。指定されたオブジェクトが java.nio.buffer ではない場合、またはオブジェクトが非整列ビュー バッファでプロセッサ アーキテクチャが整列アクセスをサポートしていない場合は、-1 を返します。仮想マシンが JNI アクセスをサポートしていない場合は、-1 を返します。

11. リフレクションのサポート

プログラマがメソッドとプロパティの名前と型を知っている場合は、JNI を直接使用して Java メソッドを呼び出したり、Java フィールドにアクセスしたりできます。Java コア リフレクション API を使用すると、実行時に Java クラスをリフレクションできます。JNI は、JNI で使用されるフィールド ID とメソッド ID と、Java Core Reflection API で使用されるフィールド オブジェクトとメソッド オブジェクトの間の一連の変換関数を提供します。

(1) 変換・取得方法ID

jmethodID FromReflectedMethod(JNIEnv *env,jobject method);

java.lang.reflect.Method または java.lang.reflect.Constructor オブジェクトをメソッド ID に変換します。

パラメータの説明:

  • env: JNIEnv インターフェイス ポインタ
  • メソッド: java.lang.reflect.Method または java.lang.reflect.Constructor オブジェクト

戻る:

  • メソッドID

(2)、属性IDを取得するための変換

jfield FromReflectedField(JNIEnv *env,jobject field);

java.lang.reflect.Field を ID に変換します。

パラメータの説明:

  • env: JNIEnv インターフェイス ポインタ
  • フィールド: java.lang.reflect.Field オブジェクト

戻る:

  • 域ID

(3) 逆変換してメソッドオブジェクトを取得する

jobject ToReflectedMethod(JNIEnv *env,jclass clazz,jmethodID methodID, jboolean isStatic);

メソッド ID を cls から java.lang.reflect.Method または java.lang.reflect.Constructor オブジェクトに変換します。メソッド ID が静的プロパティを指す場合は isStatic を JNI_TRUE に設定し、それ以外の場合は JNI_FALSE に設定する必要があります。

パラメータの説明:

  • env: JNIEnv インターフェイス ポインタ
  • clazz: Java クラス オブジェクト
  • MethodID: Java クラスに対応するメソッド ID
  • isStatic: 静的メソッドかどうか

戻る

Java レイヤーの java.lang.reflect.Method または java.lang.reflect.Constructor オブジェクトに対応します。失敗した場合は 0 を返します

異常な:

メモリが不足している場合は、OutOfMemoryError がスローされます。

(4)、逆変換して属性オブジェクトを取得

jobject ToReflectedField(JNIEnv *env,jclass cls,jfieldID field,jboolean isStatic)

属性 ID を cls から java.lang.reflect.Field オブジェクトに変換します。プロパティ ID が静的プロパティを指す場合は isStatic を JNI_TRUE に設定し、それ以外の場合は JNI_FALSE に設定する必要があります。

パラメータの説明:

  • env: JNIEnv インターフェイス ポインタ
  • cls: Java クラス オブジェクト
  • MethodID: Javaの対応する属性ID
  • isStatic: 静的プロパティかどうか

戻る:

java.lang.reflect.Field オブジェクトが正常に返され、失敗した場合は 0 が返されます。

異常な:

メモリ不足の場合は OutOfMemoryError をスローします

12. 仮想マシンの取得

jint GetJavaVM(JNIEnv *env,JavaVM **vm);

現在のスレッドに対応する Java 仮想マシン インターフェイスを返します。返された結果は vm に保存されます。

パラメータの説明:

  • env: JNI インターフェイス ポインタ
  • vm: 仮想マシンのポインタを保存します

戻る:

成功すると 0 を返し、失敗すると負の数を返します。

おすすめ

転載: blog.csdn.net/Jason_Lee155/article/details/132274563