如何从驻留在OSGi包中的类中获取JNI中的jclass

时间:2013-01-11 18:17:43

标签: java c++ java-native-interface osgi

在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包中,则不是这种情况。

要进入该类,我使用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的任何想法?

1 个答案:

答案 0 :(得分:5)

您应该能够使用辅助方法返回的jobject类型Class<Native>作为jclass,只需将其投射:

jclass nativeClass = (jclass)nativeClassInstance;