Как получить jclass в JNI из класса, находящегося в комплекте OSGi

В 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 находится в пакете OSGi, загруженном в контейнер OSGi (например, Equinox), работающий внутри JVM.

Чтобы добраться до класса, я использую функцию 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. Вызов этой функции со стороны C ++ с использованием JNI дает нам 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

Решение

Вы должны быть в состоянии использовать jobject типа Class<Native> который возвращается вашим вспомогательным методом как jclass просто приведя это:

jclass nativeClass = (jclass)nativeClassInstance;
5

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]