estoy guardando JNIEnv
en un global para poder llamar a métodos java estáticos más tarde. Pero, ¿es necesario almacenar un puntero global a la JNIEnv
como lo haría con cualquier otro objeto Java, o es un caso especial que no requiere esto.
JNIEnv* globalEnvPointer;
[JNICALL etc] void init(JNIENv* env, [etc])
{
//required?
globalEnvPointer = (JNIENv*) (env*)->GetGlobalRef(env, env);
//or is this OK?
globalEnvPointer = env;
}
Editar
Soy un poco tonto aquí, todos los métodos que usaré globalEnvPointer
se invocan dentro de mi init porque mi init
es en realidad mi c
del programa main
método, que no volverá hasta el final del programa. Tampoco estoy usando otros hilos en el programa c. Creo que esto simplifica la respuesta.
JNIEnv* globalEnvPointer;
[JNICALL etc] void main(JNIENv* env, [etc])
{
//required?
globalEnvPointer = (JNIENv*) (env*)->GetGlobalRef(env, env);
//or is this OK?
globalEnvPointer = env;
someMethod();
}
void someMethod()
{
//use globalEnvPointer here
}
No puede almacenar en caché el JNIEnv
puntero. Lee sobre ello aquí:
El puntero de la interfaz JNI (JNIEnv) solo es válido en el subproceso actual. Si otro subproceso necesita acceder a la VM de Java, primero debe llamar a AttachCurrentThread() para adjuntarse a la VM y obtener un puntero de interfaz JNI. Una vez conectado a la máquina virtual, un subproceso nativo funciona como un subproceso Java normal que se ejecuta dentro de un método nativo. El subproceso nativo permanece adjunto a la máquina virtual hasta que llama a DetachCurrentThread() para desconectarse.
Lo que puedes hacer es almacenar en caché el JavaVM
puntero en su lugar.
static JavaVM *jvm;
[JNICALL etc] void init(JNIENv* env, [etc])
{
jint rs = (*env)->GetJavaVM(env, &jvm);
assert (rs == JNI_OK);
}
Y luego cuando lo necesites entonces JNIEnv
puntero de un contexto donde no se le da hacer esto:
void someCallback() {
JNIEnv *env;
jint rs = (*jvm)->AttachCurrentThread(jvm, &env, NULL);
assert (rs == JNI_OK);
// Use the env pointer...
}
Pero cada vez que llama a un método nativo desde Java, se proporciona el puntero env para usar:
JNIEXPORT jint JNICALL Java_package_Class_method(JNIEnv *env, jobject obj) {
// just use the env pointer as is.
}