jclass
C / C ++では、宣言されたメソッドを使用してネイティブ関数をJavaクラスに登録するために値が必要ですnative
。
このJavaクラスについて考えてみましょう。
public class Native {
public native int f(int i);
}
ネイティブC/C ++関数を登録するにはNative.f()
、C++側でこれを呼び出す必要があります。
JNIEnv* env = ...;
jclass nativeClass = ...;
JNINativeMethod nativeMethod = {
(char*) "f",
(char*) "(I)I",
(void*) Java_org_example_Native_f // The native C function
};
env->RegisterNatives(nativeClass, &nativeMethod, 1);
問題のある部分はjclass
、デフォルトのクラスローダーからクラスにアクセスできない場合に値を取得することです。これは、クラスNative
が、JVM内で実行されているOSGiコンテナー(Equinoxなど)内にロードされたOSGiバンドルに存在する場合には当てはまりません。
クラスにアクセスするには、Java関数を使用してClass<?>
クラスのインスタンスを返します。
public class Helper {
public static Class<?> getNativeClass() {
// Find bundle from system bundle context.
Bundle bundle = ... // details left out.
return bundle.loadClass("org.example.Native");
}
}
この関数は、OSGiコンテナーの外部のクラスにあります。JNIを使用してC++側からこの関数を呼び出すjobject
と、のインスタンスであるが得られますjava.lang.Class<>
。
// Load the `Helper` class.
jclass helperClass = env->FindClass("org.example.Helper");
// Get the method `Helper.getNativeClass()`.
jmethodId mid = env->GetStaticMethodID(helperClass,
"getNativeClass",
"()Ljava/lang/Class;");
// Call `Helper.getNativeClass()`.
jobject nativeClassInstance = env->CallStaticObjectMethod(helperClass, mid);
問題は、(値ではなく)「jclass」値が本当に必要なことjobject
です。Native
それを取得するために、クラスのオブジェクトをインスタンス化し、jclass
そこから取得します。
// This is the jclass for 'java.lang.Class<>'.
jclass classClass = env->GetObjectClass(nativeClassInstance);
// Now get the method id for function 'newInstance()'
jmethodId newInstanceMid = env->GetMethodID(helperClass,
"newInstance",
"()Ljava/lang/Object;");
// Instantiate our 'Native' class calling 'Class<Native>.newInstance()'.
jobject nativeInstance = env->CallObjectMethod(classClass,
nativeClassInstance,
newInstanceMid);
// Now, I can get the desired 'jclass' of my 'Native' class.
jclass nativeClass = env->GetObjectClass(nativeInstance);
Native
しかし、これはクラスをインスタンス化できるためにのみ機能します。
クラスjclass
のオブジェクトをインスタンス化せずに目的を取得する方法はありますか?Native