在C / C++中,您需要一个jclass
值,以便使用声明为native
的方法将本机函数注册到Java类。
考虑这个Java类:
public class Native {
public native int f(int i);
}
要为
Native.f()
注册本机C / C++函数,我们需要在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 bundle 包中,则不是这种情况。要进入该类,我使用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
? 最佳答案
通过简单地转换它,您应该能够将辅助方法返回的jobject
类型的Class<Native>
用作jclass
:
jclass nativeClass = (jclass)nativeClassInstance;