3

在 C/C++ 中,您需要一个jclass值才能将本机函数注册到具有声明方法的 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类的对象的情况下获得期望?

4

2 回答 2

6

您应该能够通过简单地转换它来使用辅助方法返回的jobjectof 类型:Class<Native>jclass

jclass nativeClass = (jclass)nativeClassInstance;
于 2013-01-12T10:19:23.240 回答
0

如果您不需要在包中定义本机代码存根,则有一种更简单的方法来执行此操作。

将本机代码放入 JVM 类路径中的类中。org.osgi.framework.system.packages.extra=package.in.jvm启动捆绑包时使用。现在,您可以从您的 OSGi 包中获得该包,并且您可以在链接它们之后调用您的本机函数。

于 2021-10-17T18:42:06.953 回答