FindClass
、GetMethodID
、などのJNI メソッドGetFieldID
は、JVM の存続期間にわたって同じ結果を生成することが保証されている高価な操作です。これらの操作には時間がかかるため、後でネイティブ側で再利用できるように結果をどこかに保存することをお勧めします (これがキャッシングです)。
JNI キャッシングは、これらの JNI 関数呼び出しのみを考慮します。他の C++ または Java オブジェクトをキャッシュしたい場合、これは別のトピックです。(ただ明確にします)。
キャッシュされたクラス、メソッド、およびフィールドは、取得元のスレッドに依存しないため、異なるスレッド間で有効です。Set<type>Field
または を使用してオブジェクトのフィールドを取得または設定するときは、せいぜいスレッドセーフな操作を実行する必要がありますGet<type>Field
。
FindClass はクラスオブジェクトへのローカル参照を返すため、それを取得する関数が終了した後に確実に再利用できるように、それをグローバル参照に変換する必要があります。これは、NewGlobalReference を使用して実現できます。
jclass tmp_double_Class = env->FindClass( "java/lang/Double" ); // Check for exceptions!
double_Class = static_cast<jclass>( env->NewGlobalRef( tmp_double_Class ) );
if( double_Class == NULL )
return;
env->DeleteLocalRef( tmp_double_Class );
ここに、すべての JNI キャッシング トピックの例があります。
MyJni.cpp:
// Just a shortcut for checking for exceptions
#define CHECK_JNI_EXCEPTION( JNIenv ) \
if( JNIenv->ExceptionCheck() )\
{\
JNIenv->ExceptionClear();\
return JNI_FALSE;\
}\
\
// Global variables
jclass point_Class;
jmethodID point_ctor_Method;
jfieldID point_x_Field;
jfieldID point_y_Field;
JNIEXPORT jboolean JNICALL Java_com_company_package_MyClass_nativeInit( JNIEnv * env,
jclass clazz )
{
// Cache java.lang.Double class, methods and fields
jclass tmp_point_Class = env->FindClass( "android/graphics/Point" );
CHECK_JNI_EXCEPTION( env )
point_Class = static_cast<jclass>( env->NewGlobalRef( tmp_point_Class ) );
if( point_Class == NULL )
return JNI_FALSE;
env->DeleteLocalRef( tmp_point_Class );
point_ctor_Method = env->GetMethodID( point_Class, "<init>", "(II)V" );
CHECK_JNI_EXCEPTION( env )
point_x_Field = env->GetFieldID( point_Class, "x", "I" );
CHECK_JNI_EXCEPTION( env )
point_y_Field = env->GetFieldID( point_Class, "y", "I" );
CHECK_JNI_EXCEPTION( env )
return JNI_TRUE;
}
MyJni.java:
package com.company.package;
class MyClass {
// ... All java code here ...
// Trigger JNI Caching (could be also done using JNI_OnLoad...)
private static native void nativeInit();
static {
System.loadLibrary( "mylib" );
nativeInit(); // should check the result
}
}
楽しむ ;)